Определить циклы в байт-коде Java

Я пытаюсь инструментировать байт-код Java.

Я хочу распознать вход и выход из цикла Java , но я нашел идентификацию петель быть довольно сложной задачей. Я потратил несколько часов на изучение ASM и декомпиляторов с открытым исходным кодом (которые, как я думал, все время должны решать эту проблему), однако я не смог.

Инструмент, который я дополняю / расширяю, использует ASM, поэтому в идеале я хотел бы знать, как инструментировать вход и выход из различных конструкций цикла в java через ASM . Однако я также приветствовал бы рекомендацию хорошего декомпилятора с открытым исходным кодом, поскольку очевидно, что они решили бы ту же проблему.

17
задан I. J. Kennedy 26 July 2011 в 14:42
поделиться

1 ответ

Я знаю, что это - старый вопрос - однако, был определенный интерес в том, как это будет достижимо с библиотекой ASM, и это может быть полезно для будущих посетителей. При мысли о протестах, которые другие ответы дают предупреждению против обобщенных предположений, связанных с "goto" оператором, существует способ сделать это. (Это предполагает, что любая группировка кода в рамках данного метода, который может "циклично выполниться", должна быть обнаружена - обычно это - фактическая конструкция цикла, но другой (редкий, но существующий) примеры были обеспечены того, как это может произойти.)

главное, которое необходимо было бы сделать, отслеживают "маркировки" (местоположения в коде байта), который ASM посещает до того, что она называет "командой перехода" - если с маркировкой, к которой она переходит, уже встретились в контексте того же метода, затем у Вас есть потенциал для кода цикличного выполнения.

заметные различия А я видел между ответами здесь и как ASM вел себя, то, что это считало команды перехода "цикличного выполнения" для простого файла как коды операций кроме "goto" - это может быть просто изменениями в компиляции Java во время, так как это спросили, но казалось стоящим замечания.

основной пример кода для ASM - это (это вводится через checkForLoops метод):

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public void checkForLoops(Path classFile) {
    LoopClassVisitor classVisitor = new LoopClassVisitor();

    try (InputStream inputStream = Files.newInputStream(classFile)) {
        ClassReader cr = new ClassReader(inputStream);

        cr.accept(classVisitor, 0);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

public class LoopClassVisitor extends ClassVisitor {

    public LoopClassVisitor() {
        super(Opcodes.ASM7);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
            String[] exceptions) {
        return new LoopMethodVisitor();
    }

}

public class LoopMethodVisitor extends MethodVisitor {

    private List<Label> visitedLabels;

    public LoopMethodVisitor() {
        super(Opcodes.ASM7);

        visitedLabels = new ArrayList<>();
    }

    @Override
    public void visitLineNumber(final int line, final Label start) {
        System.out.println("lnLabel: " + start.toString());

        visitedLabels.add(start);
    }

    @Override
    public void visitLabel(final Label label) {
        System.out.println("vLabel: " + label.toString());

        visitedLabels.add(label);
    }

    @Override
    public void visitJumpInsn(final int opcode, final Label label) {
        System.out.println("Label: " + label.toString());

        if (visitedLabels.contains(label)) {
            System.out.println("Op: " + opcode + ", GOTO to previous command - possible looped execution");
        }
    }

}

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

0
ответ дан 30 November 2019 в 12:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: