Repository navigation
Closed
Milestone
Description
I used MessageBuffer on Android OS(4.0.3) simulator. But these error and exceptions occurred.
05-25 02:36:36.306: E/dalvikvm(12569): Could not find class 'sun.nio.ch.DirectBuffer', referenced from method org.msgpack.core.buffer.MessageBuffer.putByteBuffer
05-25 02:36:36.347: E/AndroidRuntime(12569): FATAL EXCEPTION: main
05-25 02:36:36.347: E/AndroidRuntime(12569): java.lang.ExceptionInInitializerError
05-25 02:36:36.347: E/AndroidRuntime(12569): at com.example.TestApp.MyActivity.onResume(MyActivity.java:186)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1185)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.Activity.performResume(Activity.java:5182)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2732)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2771)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2235)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.ActivityThread.access$600(ActivityThread.java:141)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.os.Handler.dispatchMessage(Handler.java:99)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.os.Looper.loop(Looper.java:137)
05-25 02:36:36.347: E/AndroidRuntime(12569): at android.app.ActivityThread.main(ActivityThread.java:5041)
05-25 02:36:36.347: E/AndroidRuntime(12569): at java.lang.reflect.Method.invokeNative(Native Method)
05-25 02:36:36.347: E/AndroidRuntime(12569): at java.lang.reflect.Method.invoke(Method.java:511)
05-25 02:36:36.347: E/AndroidRuntime(12569): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
05-25 02:36:36.347: E/AndroidRuntime(12569): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
05-25 02:36:36.347: E/AndroidRuntime(12569): at dalvik.system.NativeStart.main(Native Method)
05-25 02:36:36.347: E/AndroidRuntime(12569): Caused by: java.lang.RuntimeException: java.lang.NoSuchFieldException: theUnsafe
05-25 02:36:36.347: E/AndroidRuntime(12569): at org.msgpack.core.buffer.MessageBuffer.<clinit>(MessageBuffer.java:77)
05-25 02:36:36.347: E/AndroidRuntime(12569): ... 16 more
05-25 02:36:36.347: E/AndroidRuntime(12569): Caused by: java.lang.NoSuchFieldException: theUnsafe
05-25 02:36:36.347: E/AndroidRuntime(12569): at java.lang.Class.getDeclaredField(Class.java:631)
05-25 02:36:36.347: E/AndroidRuntime(12569): at org.msgpack.core.buffer.MessageBuffer.<clinit>(MessageBuffer.java:32)
05-25 02:36:36.347: E/AndroidRuntime(12569): ... 16 more
I think it's not an urgent issue for now. I created this issue just FYI.
Metadata
Metadata
Assignees
Labels
No labels
Activity
#101: Workaround for Android OS. Creating Unsafe instance by calling …
xerial commentedon May 26, 2014
Added a workaround for Android OS. @komamitsu Could you test this?
#101: Fix comments
xerial commentedon May 26, 2014
Unsafe instance can be found by the previous commits. The next problem is to create DirectByteBuffer instances. It looks like the constructor of DirectByteBuffer is different between Android OS and Oracle JVM.
xerial commentedon May 26, 2014
Here is a source code of DirectByteBuffer of Android:
https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/java/nio/DirectByteBuffer.java
xerial commentedon May 26, 2014
And also
sun.misc.UnsafeAPI is slightly different from Oracle JVM:https://android.googlesource.com/platform/libcore/+/master/libdvm/src/main/java/sun/misc/Unsafe.java
xerial commentedon May 26, 2014
Unsafe class in Android has not
getByte(address). Instead I foundlibcore.io.Memory.peekByte(address):https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/libcore/io/Memory.java
xerial commentedon May 26, 2014
We cannot access
libcore.iopackage andDirectByteBufferclass without using reflection. So we should provide a fallback that only usesbyte[]or ByteBuffer based access methods to memory.#101 Added several workarounds for Android OS, but this implementatio…
timnew commentedon Jan 14, 2015
Is there any update about this issue? I encounters exactly same issue.
xerial commentedon Jan 15, 2015
I'll add MessageBufferU(niversal) class, which does not depend on Unsafe and DirectByteBuffer classes.
axeon commentedon Jan 19, 2015
@xerial
Thanks for your work on android support.
String bufferClsName;
if(isJavaAtLeast7) {
if(isLittleEndian)
bufferClsName = "org.msgpack.core.buffer.MessageBuffer";
else
bufferClsName = "org.msgpack.core.buffer.MessageBufferBE";
}
else {
bufferClsName = "org.msgpack.core.buffer.MessageBufferU";
}
the code above , change to org.msgpack.core.buffer.MessageBufferX.class is better.
It can't be used for proguard, when you use class String.
xerial commentedon Jan 19, 2015
@axeon
The above switch is necessary for avoiding generation of TypeProfile for MessageBuffer methods, which is a key to achieve good performance in platform other than Android.
Is there any option in proguard to force include MessageBufferU class?
xerial commentedon Jan 19, 2015
For example, I found
http://stackoverflow.com/questions/7464035/how-to-tell-proguard-to-keep-everything
axeon commentedon Jan 19, 2015
@xerial
the new version is ok on android, but logcat print too many exception such as "can't find class sun.nio.ch.DirectBuffer/sun.misc,Unsafe".
on andorid platform ,the java.specification.version is 0.9.
I think we can add MessageBufferFactory or other class to switch MessageBuffer class, it will be disable class not found exception .
In addition ,these code is tested in android .
xerial commentedon Jan 19, 2015
@axeon
Our design decision is that we never create any interface for MassageBuffer class, because interface adds overhead to every method call due to invokeinterface call and TypeProfile generation. Speed has been the most important factor in designing msgpack v07.
Even if we create a factory class, it still needs to load MessageBuffer class (since it is a base class) and will show the warning messages you observed.
Thanks for
java.specification.versioninformation. The msgpack-core-0.7.0-p4 now usesisAndroidflag:msgpack-java/msgpack-core/src/main/java/org/msgpack/core/buffer/MessageBuffer.java
Line 122 in 629f0b3
axeon commentedon Jan 19, 2015
@xerial
Thanks for your works.
Maybe we can use MessageBufferU as base class, when detected optimized conditions is ok, then switch to MessageBufferOpt(MessageBuffer now).
This solution will be balanced performance and aesthetic design .
xerial commentedon Jan 19, 2015
@axeon
FYI. If JVM finds two or more classes that defines a method, it will generate TypeProfile. Simply writing
import MessageBufferUin a code results in generation of TypeProfile and ends up slowing down method calls of MessageBuffer.So we cannot make
MessageBufferU.getBytea base class ofMessageBuffer.getByte.For reducing warning message, we should create a different ticket and maybe worth considering to create a separate build for Android platform.
Thanks!