Как загрузить постоянный сложный объект в стек с помощью LDCInsnNode в ASM

Я хочу использовать библиотеку 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}, * {@link String} или {@link org.objectweb. .asm.Тип}.

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

person shijie xu    schedule 26.08.2015    source источник


Ответы (2)


Вы не можете.

Инструкции LDC* поддерживают (начиная с Java 7) только целые числа, числа с плавающей запятой, длинные числа, двойные числа, Strings, Classes, MethodHandles и MethodTypes. Это специальная инструкция для констант уровня байт-кода, а не для случайных объектов, которые вы хотели бы создать.

Вы можете протолкнуть нулевое значение с помощью aconst_null, но помимо этого вам придется использовать обычный код, т.е. создать объект с помощью new, затем invokespecial конструктор с нужными аргументами.

person Antimony    schedule 26.08.2015
comment
Точнее, существует специальная нестандартная возможность использовать Unsafe для создания классов, которые действительно могут иметь произвольные объекты в своем постоянном пуле как описано здесь, но исправление происходит при определении класса, а не при построении его байтового кода. И, как сказано здесь, использование библиотеки генерации кода, которая не знает, что взламывает программист, может привести к серьезным проблемам, т.е. собственная проверка кода библиотеки ASM может завершиться ошибкой для такого кода. - person Holger; 26.08.2015

Чтобы добавить к принятому ответу:

Вероятно, самый простой способ сделать это — определить постоянное значение класса как Singleton в статическом поле другого класса. Это может быть либо класс, который вы пишете на Java, либо синтетический класс. Затем, когда вам понадобится значение, просто используйте getstatic, чтобы поместить его в стек.

person Charles Forsythe    schedule 27.08.2015