Skip to content

Commit 5fd6964

Browse files
committed
Clean up MessageBuffer initialization. Add fallback to MesssageBufferU
1 parent a1991c9 commit 5fd6964

1 file changed

Lines changed: 63 additions & 53 deletions

File tree

msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java

Lines changed: 63 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)