I want to use ASM library to create a bytecode method that is capable of returning a constant value at runtime. One of class in the ASM I can use is the LdcInsnNode. So my sample code is:
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;
}
}
My question is how to load value when it is an instance of complex type (user-defined class). The document for LdcInsnNode
only says:
/** * 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;
}
You can't.
The LDC*
instructions only support (as of Java 7) ints, floats, longs, doubles, String
s, Class
es, MethodHandle
s, and MethodType
s. It's a special instruction for bytecode level constants, not whatever random objects you might like to create.
You can push a null value with aconst_null
, but apart from that you'll have to use normal code, i.e. create the object with new
, then invokespecial
the constructor with the desired arguments.