如何在 ASM 中使用 LDCInsnNode 将常量复杂对象加载到堆栈
How to load a constant complex object to a stack using LDCInsnNode in ASM
我想使用 ASM 库创建一个能够在运行时返回常量值的字节码方法。我可以使用的 ASM 中的 class 之一是 LdcInsnNode。所以我的示例代码是:
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;
}
}
我的问题是当它是复杂类型(用户定义的class)的实例时如何加载值。 LdcInsnNode
的文档只说:
/**
* The constant to be loaded on the stack. This parameter must be a non null
* {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a
* {@link String} or a {@link org.objectweb.asm.Type}.
public LdcInsnNode(final Object cst) {
super(Opcodes.LDC);
this.cst = cst;
}
你不能。
LDC*
指令仅支持(截至 Java 7)整数、浮点数、长整数、双精度数、String
s、Class
es、MethodHandle
s 和 MethodType
s。这是字节码级常量的特殊指令,而不是您可能想要创建的任何随机对象。
您可以使用 aconst_null
推送空值,但除此之外您必须使用普通代码,即使用 new
创建对象,然后 invokespecial
构造函数带有所需的参数。
要添加到已接受的答案中:
可能最简单的方法是将常量 class 值定义为另一个 class 的静态字段中的单例。这可以是您在 Java 中编写的 class 或合成的 class。然后,当您需要该值时,只需使用 getstatic 将其放入堆栈即可。
我想使用 ASM 库创建一个能够在运行时返回常量值的字节码方法。我可以使用的 ASM 中的 class 之一是 LdcInsnNode。所以我的示例代码是:
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;
}
}
我的问题是当它是复杂类型(用户定义的class)的实例时如何加载值。 LdcInsnNode
的文档只说:
/** * The constant to be loaded on the stack. This parameter must be a non null * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a * {@link String} or a {@link org.objectweb.asm.Type}.
public LdcInsnNode(final Object cst) {
super(Opcodes.LDC);
this.cst = cst;
}
你不能。
LDC*
指令仅支持(截至 Java 7)整数、浮点数、长整数、双精度数、String
s、Class
es、MethodHandle
s 和 MethodType
s。这是字节码级常量的特殊指令,而不是您可能想要创建的任何随机对象。
您可以使用 aconst_null
推送空值,但除此之外您必须使用普通代码,即使用 new
创建对象,然后 invokespecial
构造函数带有所需的参数。
要添加到已接受的答案中:
可能最简单的方法是将常量 class 值定义为另一个 class 的静态字段中的单例。这可以是您在 Java 中编写的 class 或合成的 class。然后,当您需要该值时,只需使用 getstatic 将其放入堆栈即可。