@@ -23,11 +23,26 @@ public class MessageBuffer {
2323
2424 static final boolean isUniversalBuffer ;
2525 static final Unsafe unsafe ;
26+ /**
27+ * Reference to MessageBuffer Constructors
28+ */
29+ private final static Constructor <?> mbArrConstructor ;
30+ private final static Constructor <?> mbBBConstructor ;
2631
32+ /**
33+ * The offset from the object memory header to its byte array data
34+ */
2735 static final int ARRAY_BYTE_BASE_OFFSET ;
28- static final int ARRAY_BYTE_INDEX_SCALE ;
2936
3037 static {
38+ boolean useUniversalBuffer = false ;
39+ Unsafe unsafeInstance = null ;
40+ int arrayByteBaseOffset = 16 ;
41+
42+ final String UNIVERSAL_MESSAGE_BUFFER = "org.msgpack.core.buffer.MessageBufferU" ;
43+ final String BIGENDIAN_MESSAGE_BUFFER = "org.msgpack.core.buffer.MessageBufferBE" ;
44+ final String DEFAULT_MESSAGE_BUFFER = "org.msgpack.core.buffer.MessageBuffer" ;
45+
3146 try {
3247 // Check java version
3348 String javaVersion = System .getProperty ("java.specification.version" , "" );
@@ -58,80 +73,75 @@ public class MessageBuffer {
5873 boolean isGAE = System .getProperty ("com.google.appengine.runtime.version" ) != null ;
5974
6075 // For Java6, android and JVM that has no Unsafe class, use Universal MessageBuffer
61- isUniversalBuffer =
76+ useUniversalBuffer =
6277 Boolean .parseBoolean (System .getProperty ("msgpack.universal-buffer" , "false" ))
6378 || isAndroid
6479 || isGAE
6580 || !isJavaAtLeast7
6681 || !hasUnsafe ;
6782
68- // We need to use reflection to find MessageBuffer implementation classes because
69- // importing these classes creates TypeProfile and adds some overhead to method calls.
70- String bufferClsName ;
71- if (isUniversalBuffer ) {
72- bufferClsName = "org.msgpack.core.buffer.MessageBufferU" ;
73- unsafe = null ;
74- ARRAY_BYTE_BASE_OFFSET = 16 ; // dummy value
75- ARRAY_BYTE_INDEX_SCALE = 1 ;
76- }
77- else {
78- // Check the endian of this CPU
79- boolean isLittleEndian = ByteOrder .nativeOrder () == ByteOrder .LITTLE_ENDIAN ;
80- if (isLittleEndian ) {
81- bufferClsName = "org.msgpack.core.buffer.MessageBuffer" ;
82- }
83- else {
84- bufferClsName = "org.msgpack.core.buffer.MessageBufferBE" ;
85- }
86-
83+ if (!useUniversalBuffer ) {
8784 // Fetch theUnsafe object for Oracle and OpenJDK
8885 Field field = Unsafe .class .getDeclaredField ("theUnsafe" );
8986 field .setAccessible (true );
90- unsafe = (Unsafe ) field .get (null );
91- if (unsafe == null ) {
87+ unsafeInstance = (Unsafe ) field .get (null );
88+ if (unsafeInstance == null ) {
9289 throw new RuntimeException ("Unsafe is unavailable" );
9390 }
94- ARRAY_BYTE_BASE_OFFSET = unsafe .arrayBaseOffset (byte [].class );
95- ARRAY_BYTE_INDEX_SCALE = unsafe .arrayIndexScale (byte [].class );
91+ arrayByteBaseOffset = unsafeInstance .arrayBaseOffset (byte [].class );
92+ int arrayByteIndexScale = unsafeInstance .arrayIndexScale (byte [].class );
9693
9794 // Make sure the VM thinks bytes are only one byte wide
98- if (ARRAY_BYTE_INDEX_SCALE != 1 ) {
99- throw new IllegalStateException ("Byte array index scale must be 1, but is " + ARRAY_BYTE_INDEX_SCALE );
95+ if (arrayByteIndexScale != 1 ) {
96+ throw new IllegalStateException ("Byte array index scale must be 1, but is " + arrayByteIndexScale );
10097 }
10198 }
102- Class <?> bufferCls = Class .forName (bufferClsName );
103- msgBufferClass = bufferCls ;
104-
105- Constructor <?> mbArrCstr = bufferCls .getDeclaredConstructor (byte [].class );
106- mbArrCstr .setAccessible (true );
107- mbArrConstructor = mbArrCstr ;
108-
109- Constructor <?> mbBBCstr = bufferCls .getDeclaredConstructor (ByteBuffer .class );
110- mbBBCstr .setAccessible (true );
111- mbBBConstructor = mbBBCstr ;
112-
113- // Requires Java7
114- //newMsgBuffer = MethodHandles.lookup().unreflectConstructor(mbArrCstr).asType(
115- // MethodType.methodType(bufferCls, byte[].class)
116- //);
117-
11899 }
119100 catch (Exception e ) {
120101 e .printStackTrace (System .err );
121- throw new RuntimeException (e );
102+ // Use MessageBufferU
103+ useUniversalBuffer = true ;
122104 }
123- }
105+ finally {
106+ // Initialize the static fields
107+ unsafe = unsafeInstance ;
108+ ARRAY_BYTE_BASE_OFFSET = arrayByteBaseOffset ;
124109
125- /**
126- * MessageBuffer class to use. If this machine is big-endian, it uses MessageBufferBE, which overrides some methods in this class that translate endians. If not, uses MessageBuffer.
127- */
128- private final static Class <?> msgBufferClass ;
110+ // Switch MessageBuffer implementation according to the environment
111+ isUniversalBuffer = useUniversalBuffer ;
112+ String bufferClsName ;
113+ if (isUniversalBuffer ) {
114+ bufferClsName = UNIVERSAL_MESSAGE_BUFFER ;
115+ }
116+ else {
117+ // Check the endian of this CPU
118+ boolean isLittleEndian = ByteOrder .nativeOrder () == ByteOrder .LITTLE_ENDIAN ;
119+ bufferClsName = isLittleEndian ? DEFAULT_MESSAGE_BUFFER : BIGENDIAN_MESSAGE_BUFFER ;
120+ }
129121
130- private final static Constructor <?> mbArrConstructor ;
131- private final static Constructor <?> mbBBConstructor ;
122+ try {
123+ // We need to use reflection here to find MessageBuffer implementation classes because
124+ // importing these classes creates TypeProfile and adds some overhead to method calls.
125+
126+ // MessageBufferX (default, BE or U) class
127+ Class <?> bufferCls = Class .forName (bufferClsName );
132128
133- // Requires Java7
134- //private final static MethodHandle newMsgBuffer;
129+ // MessageBufferX(byte[]) constructor
130+ Constructor <?> mbArrCstr = bufferCls .getDeclaredConstructor (byte [].class );
131+ mbArrCstr .setAccessible (true );
132+ mbArrConstructor = mbArrCstr ;
133+
134+ // MessageBufferX(ByteBuffer) constructor
135+ Constructor <?> mbBBCstr = bufferCls .getDeclaredConstructor (ByteBuffer .class );
136+ mbBBCstr .setAccessible (true );
137+ mbBBConstructor = mbBBCstr ;
138+ }
139+ catch (Exception e ){
140+ e .printStackTrace (System .err );
141+ throw new RuntimeException (e ); // No more fallback exists if MessageBuffer constructors are inaccessible
142+ }
143+ }
144+ }
135145
136146 /**
137147 * Base object for resolving the relative address of the raw byte array.
0 commit comments