我正在ASM中编写一个程序,它使用Tree API将字节码添加到某些方法中。我已经使用ASMifier来生成创建特定方法所需的代码,但是我遇到了以下问题:
mv.visitLdcInsn(Type.getType('L' + targetClassName + ';'));
我只是将mv初始化为new MethodNode
,但不是加载Class
,而是上述行在字节码中显示为:
ldc Lsome/test/TestClass; (org.objectweb.asm.Type)
如何让ASM加载java/lang/Class
常量而不是org.objectweb.asm.Type
常量?
如果相关,则下一行字节码为invokevirtual java/lang/Class getClassLoader(()Ljava/lang/ClassLoader;);
答案 0 :(得分:3)
您的代码是正确的,但不是规范的解决方案。您可以将其简化为
mv.visitLdcInsn(Type.getObjectType(targetClassName));
(在ASM中,“对象类型”表示引用类型,另请参阅Type.getObjectType(…)
和the Type.OBJECT
sort)。但是,结果是一样的。原因,为什么反汇编输出看起来像
ldc Lsome/test/TestClass; (org.objectweb.asm.Type)
在于反汇编程序。如果你看it’s code for converting an LDC instruction to a String
:
protected String printLdcInsnNode(LdcInsnNode ldc, ListIterator<?> it) { if (ldc.cst instanceof String) return nameOpcode(ldc.opcode()) + " \"" + StringEscapeUtils.escapeJava(ldc.cst.toString()) + "\" (" + ldc.cst.getClass().getCanonicalName() + ")"; return nameOpcode(ldc.opcode()) + " " + StringEscapeUtils.escapeJava(ldc.cst.toString()) + " (" + ldc.cst.getClass().getCanonicalName() + ")"; }
您将看到它将打印存储在LdcInsnNode
中的对象实例的类型,而不是代码最终将在运行时生成的类型。对于String
,这就足够了,因为它是相同的类型,对于基元,它将打印相应的包装类型,但对于Type
或Handle
个对象,此反汇编程序将向您显示这些ASM特定的类而不是相应的运行时类java.lang.Class
,java.lang.invoke.MethodType
或java.lang.invoke.MethodHandle
,ldc
指令将实际推送到操作数堆栈。
答案 1 :(得分:0)
我现在想出一个临时的解决方法。
mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandles$Lookup", "lookupClass", "()Ljava/lang/Class;", false);