Java bytecode variable index 0's className is something strange

泪湿孤枕 提交于 2019-12-12 05:24:24

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!