【问题标题】:How to load a constant complex object to a stack using LDCInsnNode in ASM如何在 ASM 中使用 LDCInsnNode 将常量复杂对象加载到堆栈中
【发布时间】:2015-08-28 23:31:18
【问题描述】:

我想使用 ASM 库来创建能够在运行时返回常量值的字节码方法。我可以使用的 ASM 中的一类是 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;

        }
}

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

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

 public LdcInsnNode(final Object cst) {
        super(Opcodes.LDC);
        this.cst = cst;
    }

【问题讨论】:

    标签: bytecode java-bytecode-asm bytecode-manipulation


    【解决方案1】:

    你不能。

    LDC* 指令仅支持(从 Java 7 开始)int、float、long、double、Strings、Classes、MethodHandles 和 MethodTypes。这是针对字节码级别常量的特殊指令,而不是您可能想要创建的任何随机对象。

    您可以使用aconst_null 推送一个空值,但除此之外您还必须使用普通代码,即使用new 创建对象,然后使用所需参数创建invokespecial 构造函数。

    【讨论】:

    • 更准确地说,有一种特殊的、非标准的可能性使用Unsafe 来创建确实可以在其常量池中具有任意对象的类,如described here,但修补发生在定义时类,而不是在构造其字节码时。 And as said here 使用不知道程序员正在破解什么的代码生成库会导致严重的问题,即 ASM 库自己的代码验证可能会在此类代码上失败。
    【解决方案2】:

    添加到已接受的答案:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多