Search code examples
bytecodejava-bytecode-asmbytecode-manipulation

How to load a constant complex object to a stack using LDCInsnNode in ASM


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;
    }

Solution

  • You can't.

    The LDC* instructions only support (as of Java 7) ints, floats, longs, doubles, Strings, Classes, MethodHandles, and MethodTypes. 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.