2121
2222import java .lang .reflect .Constructor ;
2323import java .lang .reflect .Field ;
24+ import java .lang .reflect .InvocationTargetException ;
2425import java .lang .reflect .Method ;
2526import java .nio .Buffer ;
2627import java .nio .ByteBuffer ;
@@ -52,49 +53,98 @@ final class PlatformDependent0 {
5253 private static final boolean UNALIGNED ;
5354
5455 static {
55- ByteBuffer direct = ByteBuffer .allocateDirect (1 );
56- Field addressField ;
57- try {
58- addressField = Buffer .class .getDeclaredField ("address" );
59- addressField .setAccessible (true );
60- if (addressField .getLong (direct ) == 0 ) {
61- // A direct buffer must have non-zero address.
62- addressField = null ;
56+ final ByteBuffer direct = ByteBuffer .allocateDirect (1 );
57+ final Field addressField ;
58+ // attempt to access field Buffer#address
59+ final Object maybeAddressField = AccessController .doPrivileged (new PrivilegedAction <Object >() {
60+ @ Override
61+ public Object run () {
62+ try {
63+ final Field field = Buffer .class .getDeclaredField ("address" );
64+ field .setAccessible (true );
65+ // if direct really is a direct buffer, address will be non-zero
66+ if (field .getLong (direct ) == 0 ) {
67+ return null ;
68+ }
69+ return field ;
70+ } catch (IllegalAccessException e ) {
71+ return e ;
72+ } catch (NoSuchFieldException e ) {
73+ return e ;
74+ } catch (SecurityException e ) {
75+ return e ;
76+ }
6377 }
64- } catch (Throwable t ) {
65- // Failed to access the address field.
78+ });
79+
80+ if (maybeAddressField instanceof Field ) {
81+ addressField = (Field ) maybeAddressField ;
82+ logger .debug ("java.nio.Buffer.address: available" );
83+ } else {
84+ logger .debug ("java.nio.Buffer.address: unavailable" , (Exception ) maybeAddressField );
6685 addressField = null ;
6786 }
6887
69- logger .debug ("java.nio.Buffer.address: {}" , addressField != null ? "available" : "unavailable" );
70-
7188 Unsafe unsafe ;
7289 if (addressField != null ) {
73- try {
74- Field unsafeField = Unsafe .class .getDeclaredField ("theUnsafe" );
75- unsafeField .setAccessible (true );
76- unsafe = (Unsafe ) unsafeField .get (null );
77- logger .debug ("sun.misc.Unsafe.theUnsafe: {}" , unsafe != null ? "available" : "unavailable" );
78-
79- // Ensure the unsafe supports all necessary methods to work around the mistake in the latest OpenJDK.
80- // https://github.com/netty/netty/issues/1061
81- // http://www.mail-archive.com/jdk6-dev@openjdk.java.net/msg00698.html
82- try {
83- if (unsafe != null ) {
84- unsafe .getClass ().getDeclaredMethod (
85- "copyMemory" , Object .class , long .class , Object .class , long .class , long .class );
86- logger .debug ("sun.misc.Unsafe.copyMemory: available" );
90+ // attempt to access field Unsafe#theUnsafe
91+ final Object maybeUnsafe = AccessController .doPrivileged (new PrivilegedAction <Object >() {
92+ @ Override
93+ public Object run () {
94+ try {
95+ final Field unsafeField = Unsafe .class .getDeclaredField ("theUnsafe" );
96+ unsafeField .setAccessible (true );
97+ // the unsafe instance
98+ return unsafeField .get (null );
99+ } catch (NoSuchFieldException e ) {
100+ return e ;
101+ } catch (SecurityException e ) {
102+ return e ;
103+ } catch (IllegalAccessException e ) {
104+ return e ;
87105 }
88- } catch (NoSuchMethodError t ) {
89- logger .debug ("sun.misc.Unsafe.copyMemory: unavailable" );
90- throw t ;
91- } catch (NoSuchMethodException e ) {
92- logger .debug ("sun.misc.Unsafe.copyMemory: unavailable" );
93- throw e ;
94106 }
95- } catch (Throwable cause ) {
96- // Unsafe.copyMemory(Object, long, Object, long, long) unavailable.
107+ });
108+
109+ // the conditional check here can not be replaced with checking that maybeUnsafe
110+ // is an instanceof Unsafe and reversing the if and else blocks; this is because an
111+ // instanceof check against Unsafe will trigger a class load and we might not have
112+ // the runtime permission accessClassInPackage.sun.misc
113+ if (maybeUnsafe instanceof Exception ) {
97114 unsafe = null ;
115+ logger .debug ("sun.misc.Unsafe.theUnsafe: unavailable" , (Exception ) maybeUnsafe );
116+ } else {
117+ unsafe = (Unsafe ) maybeUnsafe ;
118+ logger .debug ("sun.misc.Unsafe.theUnsafe: available" );
119+ }
120+
121+ // ensure the unsafe supports all necessary methods to work around the mistake in the latest OpenJDK
122+ // https://github.com/netty/netty/issues/1061
123+ // http://www.mail-archive.com/jdk6-dev@openjdk.java.net/msg00698.html
124+ if (unsafe != null ) {
125+ final Unsafe finalUnsafe = unsafe ;
126+ final Object maybeException = AccessController .doPrivileged (new PrivilegedAction <Object >() {
127+ @ Override
128+ public Object run () {
129+ try {
130+ finalUnsafe .getClass ().getDeclaredMethod (
131+ "copyMemory" , Object .class , long .class , Object .class , long .class , long .class );
132+ return null ;
133+ } catch (NoSuchMethodException e ) {
134+ return e ;
135+ } catch (SecurityException e ) {
136+ return e ;
137+ }
138+ }
139+ });
140+
141+ if (maybeException == null ) {
142+ logger .debug ("sun.misc.Unsafe.copyMemory: available" );
143+ } else {
144+ // Unsafe.copyMemory(Object, long, Object, long, long) unavailable.
145+ unsafe = null ;
146+ logger .debug ("sun.misc.Unsafe.copyMemory: unavailable" , (Exception ) maybeException );
147+ }
98148 }
99149 } else {
100150 // If we cannot access the address of a direct buffer, there's no point of using unsafe.
@@ -113,14 +163,43 @@ final class PlatformDependent0 {
113163 Constructor <?> directBufferConstructor ;
114164 long address = -1 ;
115165 try {
116- directBufferConstructor = direct .getClass ().getDeclaredConstructor (long .class , int .class );
117- directBufferConstructor .setAccessible (true );
118- address = UNSAFE .allocateMemory (1 );
119-
120- // Try to use the constructor now
121- directBufferConstructor .newInstance (address , 1 );
122- } catch (Throwable t ) {
123- directBufferConstructor = null ;
166+ final Object maybeDirectBufferConstructor =
167+ AccessController .doPrivileged (new PrivilegedAction <Object >() {
168+ @ Override
169+ public Object run () {
170+ try {
171+ final Constructor constructor =
172+ direct .getClass ().getDeclaredConstructor (long .class , int .class );
173+ constructor .setAccessible (true );
174+ return constructor ;
175+ } catch (NoSuchMethodException e ) {
176+ return e ;
177+ } catch (SecurityException e ) {
178+ return e ;
179+ }
180+ }
181+ });
182+
183+ if (maybeDirectBufferConstructor instanceof Constructor <?>) {
184+ address = UNSAFE .allocateMemory (1 );
185+ // try to use the constructor now
186+ try {
187+ ((Constructor ) maybeDirectBufferConstructor ).newInstance (address , 1 );
188+ directBufferConstructor = (Constructor <?>) maybeDirectBufferConstructor ;
189+ logger .debug ("direct buffer constructor: available" );
190+ } catch (InstantiationException e ) {
191+ directBufferConstructor = null ;
192+ } catch (IllegalAccessException e ) {
193+ directBufferConstructor = null ;
194+ } catch (InvocationTargetException e ) {
195+ directBufferConstructor = null ;
196+ }
197+ } else {
198+ logger .debug (
199+ "direct buffer constructor: unavailable" ,
200+ (Exception ) maybeDirectBufferConstructor );
201+ directBufferConstructor = null ;
202+ }
124203 } finally {
125204 if (address != -1 ) {
126205 UNSAFE .freeMemory (address );
@@ -130,25 +209,46 @@ final class PlatformDependent0 {
130209
131210 ADDRESS_FIELD_OFFSET = objectFieldOffset (addressField );
132211 boolean unaligned ;
133- try {
134- Class <?> bitsClass = Class .forName ("java.nio.Bits" , false , ClassLoader .getSystemClassLoader ());
135- Method unalignedMethod = bitsClass .getDeclaredMethod ("unaligned" );
136- unalignedMethod .setAccessible (true );
137- unaligned = Boolean .TRUE .equals (unalignedMethod .invoke (null ));
138- } catch (Throwable t ) {
139- // We at least know x86 and x64 support unaligned access.
212+ Object maybeUnaligned = AccessController .doPrivileged (new PrivilegedAction <Object >() {
213+ @ Override
214+ public Object run () {
215+ try {
216+ Class <?> bitsClass =
217+ Class .forName ("java.nio.Bits" , false , PlatformDependent .getSystemClassLoader ());
218+ Method unalignedMethod = bitsClass .getDeclaredMethod ("unaligned" );
219+ unalignedMethod .setAccessible (true );
220+ return unalignedMethod .invoke (null );
221+ } catch (ClassNotFoundException e ) {
222+ return e ;
223+ } catch (NoSuchMethodException e ) {
224+ return e ;
225+ } catch (InvocationTargetException e ) {
226+ return e ;
227+ } catch (IllegalAccessException e ) {
228+ return e ;
229+ } catch (SecurityException e ) {
230+ return e ;
231+ }
232+ }
233+ });
234+
235+ if (maybeUnaligned instanceof Boolean ) {
236+ unaligned = (Boolean ) maybeUnaligned ;
237+ logger .debug ("java.nio.Bits.unaligned: available, {}" , unaligned );
238+ } else {
140239 String arch = SystemPropertyUtil .get ("os.arch" , "" );
141240 //noinspection DynamicRegexReplaceableByCompiledPattern
142241 unaligned = arch .matches ("^(i[3-6]86|x86(_64)?|x64|amd64)$" );
242+ Exception e = (Exception ) maybeUnaligned ;
243+ logger .debug ("java.nio.Bits.unaligned: unavailable, " + unaligned , e );
143244 }
144245
145246 UNALIGNED = unaligned ;
146- logger .debug ("java.nio.Bits.unaligned: {}" , UNALIGNED );
147247 BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset ();
148248 }
149249
150250 logger .debug ("java.nio.DirectByteBuffer.<init>(long, int): {}" ,
151- DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable" );
251+ DIRECT_BUFFER_CONSTRUCTOR != null ? "available" : "unavailable" );
152252
153253 freeDirectBuffer (direct );
154254 }
0 commit comments