Bytecode 如何在ASM中使用ldcinsnode将常量复杂对象加载到堆栈

Bytecode 如何在ASM中使用ldcinsnode将常量复杂对象加载到堆栈,bytecode,java-bytecode-asm,bytecode-manipulation,Bytecode,Java Bytecode Asm,Bytecode Manipulation,我想使用ASM库创建一个字节码方法,该方法能够在运行时返回常量值。我可以使用ASM中的一个类是ldcinsnode。因此,我的示例代码是: class Myclass{ final const Object value; @Override public MethodNode get(String clsName, String mhName){ int access = Opcodes.ACC_PUBLIC| Opcodes.ACC_STA

我想使用ASM库创建一个字节码方法,该方法能够在运行时返回常量值。我可以使用ASM中的一个类是ldcinsnode。因此,我的示例代码是:

class Myclass{

final const Object value; 

    @Override
    public MethodNode get(String clsName, String mhName){   

            int access = Opcodes.ACC_PUBLIC| Opcodes.ACC_STATIC;
            MethodNode methodNode = new MethodNode(ASM5, access, mhName, type.toString(), null, null);
            methodNode.instructions.add(new LdcInsnNode(value));
            Type returnType = Type.getReturnType(type.toMethodDescriptorString());
            if(!returnType.getInternalName().equals(Type.getDescriptor(value.getClass))){
                methodNode.instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, returnType.getInternalName()));
            }
            methodNode.instructions.add(new InsnNode(Opcodes.ARETURN));
            return new methodNode;

        }
}
我的问题是,当值是复杂类型(用户定义类)的实例时,如何加载它。
LdcInsnNode
的文档仅说明:

/** *要加载到堆栈上的常量。此参数必须为非null *{@link Integer},a{@link Float},a{@link Long},a{@link Double},a *{@link String}或{@link org.objectweb.asm.Type}

你不能

LDC*
指令仅支持(从Java 7开始)整数、浮点、长整数、双精度、
String
s、
Class
es、
MethodHandle
s和
MethodType
s。这是一个字节码级常量的特殊指令,而不是您想要创建的任何随机对象


您可以使用
acost\u null
推送空值,但除此之外,您还必须使用普通代码,即使用
new
创建对象,然后
调用具有所需参数的构造函数。

要添加到接受的答案:


可能最简单的方法是将常量类值定义为另一个类的静态字段中的单例。这可以是用Java编写的类,也可以是合成类。然后,当需要该值时,只需使用getstatic将其放在堆栈上

更准确地说,有一种特殊的、非标准的可能性,可以使用
Unsafe
创建类,这些类的常量池中确实可以有任意对象,但修补是在定义类时发生的,而不是在构造其字节码时发生的。使用不知道程序员正在攻击什么的代码生成库可能会导致严重问题,即ASM库自身的代码验证可能会在此类代码上失败。
 public LdcInsnNode(final Object cst) {
        super(Opcodes.LDC);
        this.cst = cst;
    }