@@ -27,10 +27,18 @@ public class MessageBuffer {
2727 static final Constructor byteBufferConstructor ;
2828
2929 static final Class <?> directByteBufferClass ;
30- static final boolean isByteBufferConstructorTakesBufferReference ;
30+ static final DirectBufferConstructorType directBufferConstructorType ;
31+ static final Method memoryBlockWrapFromJni ;
3132 static final int ARRAY_BYTE_BASE_OFFSET ;
3233 static final int ARRAY_BYTE_INDEX_SCALE ;
3334
35+ enum DirectBufferConstructorType {
36+ ARGS_LONG_INT_REF ,
37+ ARGS_LONG_INT ,
38+ ARGS_INT_INT ,
39+ ARGS_MB_INT_INT
40+ }
41+
3442 static {
3543 try {
3644 // Check java version
@@ -82,19 +90,35 @@ public class MessageBuffer {
8290 // Find the hidden constructor for DirectByteBuffer
8391 directByteBufferClass = ClassLoader .getSystemClassLoader ().loadClass ("java.nio.DirectByteBuffer" );
8492 Constructor directByteBufferConstructor = null ;
85- boolean isAcceptReference = true ;
93+ DirectBufferConstructorType constructorType = null ;
94+ Method mbWrap = null ;
8695 try {
8796 // TODO We should use MethodHandle for Java7, which can avoid the cost of boxing with JIT optimization
8897 directByteBufferConstructor = directByteBufferClass .getDeclaredConstructor (long .class , int .class , Object .class );
98+ constructorType = DirectBufferConstructorType .ARGS_LONG_INT_REF ;
8999 }
90- catch (NoSuchMethodException e ) {
91- // https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/nio/DirectByteBuffer.java
92- // DirectByteBuffer(long address, int capacity)
93- directByteBufferConstructor = directByteBufferClass .getDeclaredConstructor (long .class , int .class );
94- isAcceptReference = false ;
100+ catch (NoSuchMethodException e0 ) {
101+ try {
102+ // https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/nio/DirectByteBuffer.java
103+ // DirectByteBuffer(long address, int capacity)
104+ directByteBufferConstructor = directByteBufferClass .getDeclaredConstructor (long .class , int .class );
105+ constructorType = DirectBufferConstructorType .ARGS_LONG_INT ;
106+ } catch (NoSuchMethodException e1 ) {
107+ try {
108+ directByteBufferConstructor = directByteBufferClass .getDeclaredConstructor (int .class , int .class );
109+ constructorType = DirectBufferConstructorType .ARGS_INT_INT ;
110+ } catch (NoSuchMethodException e2 ) {
111+ Class <?> aClass = Class .forName ("java.nio.MemoryBlock" );
112+ mbWrap = aClass .getDeclaredMethod ("wrapFromJni" , int .class , long .class );
113+ mbWrap .setAccessible (true );
114+ directByteBufferConstructor = directByteBufferClass .getDeclaredConstructor (aClass , int .class , int .class );
115+ constructorType = DirectBufferConstructorType .ARGS_MB_INT_INT ;
116+ }
117+ }
95118 }
96119 byteBufferConstructor = directByteBufferConstructor ;
97- isByteBufferConstructorTakesBufferReference = isAcceptReference ;
120+ directBufferConstructorType = constructorType ;
121+ memoryBlockWrapFromJni = mbWrap ;
98122 if (byteBufferConstructor == null )
99123 throw new RuntimeException ("Constructor of DirectByteBuffer is not found" );
100124
@@ -510,10 +534,26 @@ public ByteBuffer toByteBuffer(int index, int length) {
510534 return ByteBuffer .wrap ((byte []) base , (int ) ((address - ARRAY_BYTE_BASE_OFFSET ) + index ), length );
511535 }
512536 try {
513- if (isByteBufferConstructorTakesBufferReference )
514- return (ByteBuffer ) byteBufferConstructor .newInstance (address + index , length , reference );
515- else
516- return (ByteBuffer ) byteBufferConstructor .newInstance (address + index , length );
537+ ByteBuffer bb = null ;
538+ switch (directBufferConstructorType ) {
539+ case ARGS_LONG_INT_REF :
540+ bb = (ByteBuffer ) byteBufferConstructor .newInstance (address + index , length , reference );
541+ break ;
542+ case ARGS_LONG_INT :
543+ bb = (ByteBuffer ) byteBufferConstructor .newInstance (address + index , length );
544+ break ;
545+ case ARGS_INT_INT :
546+ bb = (ByteBuffer ) byteBufferConstructor .newInstance ((int )address + index , length );
547+ break ;
548+ case ARGS_MB_INT_INT :
549+ bb = (ByteBuffer ) byteBufferConstructor .newInstance (
550+ memoryBlockWrapFromJni .invoke (null , address + index , length ),
551+ length , 0 );
552+ break ;
553+ default :
554+ throw new IllegalStateException ("Unexpected value" );
555+ }
556+ return bb ;
517557 }
518558 catch (Throwable e ) {
519559 // Convert checked exception to unchecked exception
0 commit comments