1818import java .lang .reflect .Constructor ;
1919import java .lang .reflect .InvocationTargetException ;
2020import java .lang .reflect .Method ;
21+ import java .nio .Buffer ;
2122import java .nio .ByteBuffer ;
2223import java .security .AccessController ;
2324import java .security .PrivilegedAction ;
2425
2526import sun .misc .Unsafe ;
27+ import sun .nio .ch .DirectBuffer ;
2628
2729/**
2830 * Wraps the difference of access methods to DirectBuffers between Android and others.
2931 */
3032class DirectBufferAccess
3133{
3234 private DirectBufferAccess ()
33- {}
35+ {
36+ }
3437
3538 enum DirectBufferConstructorType
3639 {
@@ -40,7 +43,6 @@ enum DirectBufferConstructorType
4043 ARGS_MB_INT_INT
4144 }
4245
43- static Method mGetAddress ;
4446 // For Java <=8, gets a sun.misc.Cleaner
4547 static Method mCleaner ;
4648 static Method mClean ;
@@ -95,10 +97,19 @@ enum DirectBufferConstructorType
9597 if (byteBufferConstructor == null ) {
9698 throw new RuntimeException ("Constructor of DirectByteBuffer is not found" );
9799 }
98- byteBufferConstructor .setAccessible (true );
99100
100- mGetAddress = directByteBufferClass .getDeclaredMethod ("address" );
101- mGetAddress .setAccessible (true );
101+ try {
102+ byteBufferConstructor .setAccessible (true );
103+ }
104+ catch (RuntimeException e ) {
105+ // This is a Java9+ exception, so we need to detect it without importing it for Java8 support
106+ if ("java.lang.reflect.InaccessibleObjectException" .equals (e .getClass ().getName ())) {
107+ byteBufferConstructor = null ;
108+ }
109+ else {
110+ throw e ;
111+ }
112+ }
102113
103114 if (MessageBuffer .javaVersion <= 8 ) {
104115 setupCleanerJava6 (direct );
@@ -160,6 +171,7 @@ public Object run()
160171
161172 /**
162173 * Checks if we have a usable {@link DirectByteBuffer#cleaner}.
174+ *
163175 * @param direct a direct buffer
164176 * @return the method or an error
165177 */
@@ -184,6 +196,7 @@ private static Object getCleanerMethod(ByteBuffer direct)
184196
185197 /**
186198 * Checks if we have a usable {@link sun.misc.Cleaner#clean}.
199+ *
187200 * @param direct a direct buffer
188201 * @param mCleaner the {@link DirectByteBuffer#cleaner} method
189202 * @return the method or null
@@ -210,6 +223,7 @@ private static Object getCleanMethod(ByteBuffer direct, Method mCleaner)
210223
211224 /**
212225 * Checks if we have a usable {@link Unsafe#invokeCleaner}.
226+ *
213227 * @param direct a direct buffer
214228 * @return the method or an error
215229 */
@@ -218,7 +232,7 @@ private static Object getInvokeCleanerMethod(ByteBuffer direct)
218232 try {
219233 // See https://bugs.openjdk.java.net/browse/JDK-8171377
220234 Method m = MessageBuffer .unsafe .getClass ().getDeclaredMethod (
221- "invokeCleaner" , ByteBuffer .class );
235+ "invokeCleaner" , ByteBuffer .class );
222236 m .invoke (MessageBuffer .unsafe , direct );
223237 return m ;
224238 }
@@ -233,17 +247,9 @@ private static Object getInvokeCleanerMethod(ByteBuffer direct)
233247 }
234248 }
235249
236- static long getAddress (Object base )
250+ static long getAddress (Buffer buffer )
237251 {
238- try {
239- return (Long ) mGetAddress .invoke (base );
240- }
241- catch (IllegalAccessException e ) {
242- throw new RuntimeException (e );
243- }
244- catch (InvocationTargetException e ) {
245- throw new RuntimeException (e );
246- }
252+ return ((DirectBuffer ) buffer ).address ();
247253 }
248254
249255 static void clean (Object base )
@@ -253,7 +259,7 @@ static void clean(Object base)
253259 Object cleaner = mCleaner .invoke (base );
254260 mClean .invoke (cleaner );
255261 }
256- else {
262+ else {
257263 mInvokeCleaner .invoke (MessageBuffer .unsafe , base );
258264 }
259265 }
@@ -269,6 +275,10 @@ static boolean isDirectByteBufferInstance(Object s)
269275
270276 static ByteBuffer newByteBuffer (long address , int index , int length , ByteBuffer reference )
271277 {
278+ if (byteBufferConstructor == null ) {
279+ throw new IllegalStateException ("Can't create a new DirectByteBuffer. In JDK17+, two JVM options needs to be set: " +
280+ "--add-opens=java.base/java.nio=ALL-UNNAMED and --add-opens=java.base/sun.nio.ch=ALL-UNNAMED" );
281+ }
272282 try {
273283 switch (directBufferConstructorType ) {
274284 case ARGS_LONG_INT_REF :
0 commit comments