Байт-код Java - ASM - Получить смещение метки

Я пытаюсь получить смещения всех меток в методе.

Я попытался использовать следующий код:

private static ArrayList<Integer> GetLabelOffsets(MethodNode methodNode) {
    ArrayList<Integer> labelOffsets = new ArrayList<>();

    for (AbstractInsnNode instruction : methodNode.instructions.toArray()) {
        if (instruction instanceof JumpInsnNode) {
            JumpInsnNode jumpInsnNode = (JumpInsnNode) instruction;
            labelOffsets.add(jumpInsnNode.label.getLabel().getOffset());.
        }
    }

    return labelOffsets;
}

Однако метод getOffset() выдает Exception:

java.lang.IllegalStateException: Label offset position has not been resolved yet

Как я могу разрешить эти смещенные позиции? Или как правильно этого добиться?

Редактировать

MethodNode — это объект org.objectweb.asm.tree.MethodNode из библиотеки Java ASM.

Добавлен код по запросу:

public static HashMap<String, ClassNode> ParseJar(JarFile jar) {
    HashMap<String, ClassNode> classes = new HashMap<>();

    try {
        Enumeration<?> enumeration = jar.entries();
        while (enumeration.hasMoreElements()) {
            JarEntry entry = (JarEntry) enumeration.nextElement();

            if (entry.getName().endsWith(".class")) {
                ClassReader classReader = new ClassReader(jar.getInputStream(entry));
                ClassNode classNode = new ClassNode();
                classReader.accept(classNode, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
                classes.put(classNode.name, classNode);
            }

        }
        jar.close();
        return classes;
    } catch (Exception ex) {
        return null;
    }
}

public static void main(String[] args) {
    JarFile jar = new JarFile(fileName);
    HashMap<String, ClassNode> classes = JarUtils.ParseJar(jar);
    for (ClassNode classNode : classes.values()) {
        for (MethodNode methodNode : classNode.methods) {
            ArrayList<Integer> offsets = GetLabelOffsets(methodNode);
            // do more stuff with offsets
        }
    }
}

person eKKiM    schedule 23.11.2017    source источник
comment
Не могли бы вы предоставить (опубликовать) минимальный, полный и проверяемый пример?   -  person Sergey Vyacheslavovich Brunov    schedule 24.11.2017
comment
Спасибо за обновления! Какой файл jar следует использовать в качестве входных данных программы для воспроизведения проблемы?   -  person Sergey Vyacheslavovich Brunov    schedule 24.11.2017
comment
Подойдет любой файл jar. Пока он содержит (не)условный переход в байт-коде.   -  person eKKiM    schedule 24.11.2017
comment
Я не пишу метод. Мне нужна эта информация для анализа существующего метода.   -  person eKKiM    schedule 24.11.2017


Ответы (1)


Из документации getOffset():

Этот метод предназначен для подклассов атрибутов и обычно не требуется генераторам классов или адаптерам.

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

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

В списке инструкций должен быть соответствующий LabelNode ссылается на тот же Label, что и инструкция.

person Holger    schedule 24.11.2017
comment
Спасибо! похоже, я слишком усложнял это. Таким образом, это работает и намного проще/чище. - person eKKiM; 24.11.2017