ASM посмотреть на maxStack перед инструкциями? - PullRequest
3 голосов
/ 22 января 2020

Я пытаюсь использовать библиотеку ASM для перевода байтового кода в другой формат, что можно сделать с помощью MethodVisitor, как с этим простым тестовым кодом:

    return new MethodVisitor(ASM7) {
        @Override
        public void visitInsn(int opcode) {
            System.out.println(String.format("%02x", opcode));
        }

        @Override
        public void visitMaxs(int maxStack, int maxLocals) {
            System.out.println(maxStack);
        }
    };

Одна проблема заключается в том, что я добираться до maxStack только после фактических инструкций - я проверил это, и это - порядок, в котором вызываются методы - тогда как было бы полезно иметь значение maxStack доступным при переводе инструкций.

Is есть ли способ увидеть maxStack первым?

Ответы [ 2 ]

3 голосов
/ 23 января 2020

ASM API не поддерживает доступ к этой информации до обхода инструкций.

Одним из решений будет двойной обход класса, сохранение максимальных значений в первом проходе.

Альтернатива временно хранить информацию о текущем методе. Дерево API ASM может помочь вам здесь. Класс MethodNode реализует MethodVisitor, хранит все посещенные артефакты и имеет accept(MethodVisitor) для посещения всех сохраненных артефактов:

classReader.accept(new ClassVisitor(Opcodes.ASM7) {
    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor,
                                     String signature, String[] exceptions) {
        MethodVisitor actualVisitor = new MethodVisitor(Opcodes.ASM7) {
            @Override
            public void visitInsn(int opcode) {
                System.out.printf("%02x%n", opcode);
            }

            @Override
            public void visitMaxs(int maxStack, int maxLocals) {
                System.out.println("max stack: "+maxStack);
            }
        };
        return new MethodNode(Opcodes.ASM7) {
            @Override
            public void visitMaxs(int maxStack, int maxLocals) {
                actualVisitor.visitMaxs(maxStack, maxLocals);
                super.visitMaxs(maxStack, maxLocals);
            }
            @Override
            public void visitEnd() {
                accept(actualVisitor);
            }
        };
    }
}, 0);

Так что здесь мы сохраняем исходный MethodVisitor как есть, но возвращаем адаптер, реализующий предполагаемую модификацию. Это подкласс MethodNode, записывающий все артефакты, но сообщающий visitMaxs немедленно actualVisitor, затем на visitEnd будет accept(actualVisitor) для просмотра всей записанной информации.

Обратите внимание, что, следовательно, actualVisitor встретится visitMaxs дважды, один раз перед всеми другими элементами, затем снова в стандартной последовательности событий.

0 голосов
/ 22 января 2020

Максимальный стек, рассчитанный для метода, зависит от инструкций и путей через тело метода. Следовательно, максимальный стек будет доступен только после анализа тела метода. Обратитесь к разделам 3.3.1, 3.3.2 и 3.5 здесь .

. Вы можете получить максимальный стек в отдельном проходе и сохранить его для справки в будущих проходах. Однако изменение тела метода, вероятно, может сделать недействительной такую ​​хранимую информацию стека.

...