Java字节码 - ASM - 获取标签偏移量

时间:2017-11-23 21:47:42

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

我正试图获取方法中所有标签的偏移量。

我尝试使用以下代码:

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是来自Java ASM库的org.objectweb.asm.tree.MethodNode对象

根据要求添加了更多代码:

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
        }
    }
}

1 个答案:

答案 0 :(得分:4)

来自documentation of getOffset()

  

此方法适用于属性子类,类生成器或适配器通常不需要。

由于此偏移量是根据 bytes 定义的,因此在处理指令列表时不会非常有用,特别是当ASM抽象出不同形式的指令时在字节码中可能有不同的长度。

一般的想法是可以更改此指令列表,因此Label表示逻辑位置,并且在编写方法的结果字节码时将计算偏移量,并且实际数字是已知的。

在指令列表中,应该有一个对应的LabelNode引用与指令相同的Label