本文介绍了Java字节码变量索引0的className有点奇怪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用ASM库生成字节码,并使用Unsafe.defineAnonymous作为类加载它们.两种方法在大多数情况下都可以工作,但是经过很短的时间后,它就会失败.然后,我在发出的字节码中添加了一些调试指令以打印某些内容,并且输出使我困惑了两周.

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是GuardWithTestHandle的缩写).

(GWT is short for GuardWithTestHandle).

1,生成两个类:DYNGWT70和DYNGWT73,并且都使用Unsafe加载.对于每个类,仅创建一个实例.

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,DYNGWT70的布局类似于:

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具有相似的结构.

DYNGWT73 has similar structure.

但是第一个tempDebug的输出是:

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

我不明白mh.getClass().getName()java.lang.invoke.DYNGuardWithTestHandle73/0000000052DFAE40,应该是DYNGuardWithTestHandle**70**/0000000052DFAExxx在此处发布堆栈的目的是为了表明它正在运行DYN70的方法,并且异常与混乱点有关...

I can not understand mh.getClass().getName() is the java.lang.invoke.DYNGuardWithTestHandle73/0000000052DFAE40, it should be something DYNGuardWithTestHandle**70**/0000000052DFAExxxThe 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.

推荐答案

如果您使用不安全的非标准API,请至少阅读其注释.最好不要完全依赖内部API.您正在定义匿名类-不要期望其具有有效的名称.

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.

Unsafe.defineAnonymousClass的评论说:

// 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.

因此,/0000000052DFAE40有意附加在defineAnonymousClass后面.例如,您可能会两次加载相同的类字节(对于常规的ClassLoader而言是无法做到的),并且将生成不同的后缀,以避免名称冲突.

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.

这篇关于Java字节码变量索引0的className有点奇怪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-28 06:37
查看更多