问题
I use ASM library to generate bytecodes and load them using Unsafe.defineAnonymous
as a Class. Both work in most of cases, but after for a short time, it fails. Then I add some debug instructions in the emitted bytecodes to print something, and the output confused me for two weeks.
(GWT is short for GuardWithTestHandle).
1, Two classes are generated: DYNGWT70 and DYNGWT73, and both are loaded using Unsafe
. For each class, there is only one instance is created.
2, The layout of DYNGWT70 is something like:
public class java.lang.invoke.DYNGuardWithTestHandle70 extends java.lang.invoke.BaseTemplate{
public org.jruby.runtime.builtin.IRubyObject inlinedMethod(org.jruby.runtime.ThreadContext, org.jruby.runtime.builtin.IRubyObject, org.jruby.runtime.builtin.IRubyObject) throws java.lang.Throwable;
flags: ACC_PUBLIC
Code:
stack=8, locals=22, args_size=4
0: aload_0
1: aload_0
2: ldc #29 // String This is Guard java/lang/invoke/DYNGuardWithTestHandle70
4: invokestatic #32 // Method java/lang/invoke/BaseTemplate.tempDebug:(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;)V
7: astore 4
9: aload 4
.....
}
}
protected static void tempDebug(MethodHandle mh, String name){
System.err.println("___________Debug: "+mh.getClass().getName()+", "+mh.toString()+ " message="+name);
}
DYNGWT73 has similar structure.
But the output for the first tempDebug is:
___________Debug: java.lang.invoke.DYNGuardWithTestHandle73/0000000052DFAE40, MethodHandle(ThreadContext,IRubyObject,IRubyObject)IRubyObject uid:9a7bf505-8845-4594-9cf8-69f392eef869 message= This is Guard java/lang/invoke/DYNGuardWithTestHandle70
......
16/Aug/2016:22:13:42:834 -0300 [main] DEBUG java.lang.invoke.BaseTemplate - TypeInconsistException [_mh=MethodHandle(ThreadContext,IRubyObject,IRubyObject)IRubyObject uid:e064b157-f615-4f20-b386-947fc20c61ad, _exce=***** false (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;J)Lorg/jruby/runtime/builtin/IRubyObject;]
TypeInconsistException [_mh=MethodHandle(ThreadContext,IRubyObject,IRubyObject)IRubyObject uid:e064b157-f615-4f20-b386-947fc20c61ad, _exce=***** false (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;)Lorg/jruby/runtime/builtin/IRubyObject; (Lorg/jruby/runtime/ThreadContext;Lorg/jruby/runtime/builtin/IRubyObject;Lorg/jruby/runtime/builtin/IRubyObject;J)Lorg/jruby/runtime/builtin/IRubyObject;]
at java.lang.invoke.BaseTemplate.debugCompareReceiverTypeMethodDesc(BaseTemplate.java:59)
at java.lang.invoke.DYNGuardWithTestHandle70.0000000052B50680.inlinedMethod(Unknown Source)
at java.lang.invoke.DYNGuardWithTestHandle70.0000000052B50680.invokeExact_thunkArchetype_L(Unknown Source)
at java.lang.invoke.MutableCallSiteDynamicInvokerHandle.invokeExact_thunkArchetype_X(MutableCallSiteDynamicInvok
I can not understand mh.getClass().getName()
is the java.lang.invoke.DYNGuardWithTestHandle73/0000000052DFAE40
, it should be something DYNGuardWithTestHandle**70**/0000000052DFAExxx
The purpose of posting stack here is to show that it is DYN70's method running and the exception is related to the confusing point,..
This error does not always occur, though the frequency is high. Anyone have experienced similar strange case? Thanks for your suggestion.
回答1:
If you use unsafe nonstandard APIs, please at least read comments to it. Better not to rely on internal APIs at all. You are defining an anonymous class - don't expect it to have a valid name.
The comments to Unsafe.defineAnonymousClass
say:
// When you load an anonymous class U, it works as if you changed its name just before loading,
// to a name that you will never use again. Since the name is lost, no other class can directly
// link to any member of U.
So, /0000000052DFAE40
is intentionally appended by defineAnonymousClass
. For example, you may load the same class bytes twice (what you can't do with a regular ClassLoader), and different suffixes will be generated to avoid name clash.
来源:https://stackoverflow.com/questions/38986780/java-bytecode-variable-index-0s-classname-is-something-strange