1

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;
    }
shijie xu
  • 1,975
  • 21
  • 52

2 Answers2

2

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.

Antimony
  • 37,781
  • 10
  • 100
  • 107
  • To be more precisely, there is the special, non-standard possibility to use `Unsafe` to create classes which can indeed have arbitrary objects in their constant pool as [described here](http://stackoverflow.com/a/31454520/2711488) but the patching happens when defining the class, not when constructing its byte code. [And as said here](http://stackoverflow.com/a/25742154/2711488) using a code generation library which is not aware of what the programmer is hacking can lead to severe problems, i.e. the ASM library’s own code verification may fail on such code. – Holger Aug 26 '15 at 17:18
0

To add to the accepted answer:

Probably the easiest way to do this is to define your constant class value as a Singleton in a static field of another class. This can either be a class you write in Java or a synthetic class. Then, when you need the value, just use getstatic to put it on the stack.

Charles Forsythe
  • 1,831
  • 11
  • 12