【问题标题】:How to determine line number for the method with java ASM?如何使用 java ASM 确定方法的行号?
【发布时间】:2018-04-23 17:33:19
【问题描述】:

我需要使用 ObjectWeb ASM 库确定类中特定方法的行号。
方法声明的行号或方法主体中的第一行同样被接受为正确答案(例如 6 或 7)。

示例:

1. public class Foo {
  ...
6.     public void bar() {
7.           try {
8.                try {
9.                     System.out.println(); //first executable line

我尝试使用 MethodVisitor 的 visitLineNumber 方法,但它只访问第一个可执行行(例如第 9 行)。
我在 JavaAssist 库 (link) 上找到了解决此问题的方法。
但是有没有办法用 ASM 解决这个问题?

编辑:

sn-p 之后的结果相同,第 9 行而不是第 6 行或第 7 行。

public static int getLineNumber(String path) throws IOException {
        final File f = new File(path);
        try (FileInputStream fis = new FileInputStream(f)) {
            ClassReader reader = new ClassReader(fis);
            ClassNode clNode = new ClassNode(Opcodes.ASM5);
            reader.accept(clNode, Opcodes.ASM5);
            for (MethodNode mNode : (List<MethodNode>) clNode.methods) {
                if (mNode.name.equals("bar")) {
                    ListIterator<AbstractInsnNode> it = mNode.instructions.iterator();
                    while (it.hasNext()) {
                        AbstractInsnNode inNode = it.next();
                        if (inNode instanceof LineNumberNode) {
                            return ((LineNumberNode) inNode).line;
                        }
                    }
                }
            }
        }
        return -1;
    }

【问题讨论】:

    标签: java bytecode java-bytecode-asm line-numbers


    【解决方案1】:

    任何字节码处理库提供的行号都基于LineNumberTable attribute,它将方法的可执行指令映射到行号。因此,在类文件中找不到不会导致生成可执行字节码的源代码行是一个基本限制。

    有时它甚至取决于编译器,将跨多行的构造分配给哪个源代码行。

    【讨论】:

      【解决方案2】:
      public static LineNumberNode findLineNumberForInstruction(InsnList 
      insnList, AbstractInsnNode insnNode) {
          Validate.notNull(insnList);
          Validate.notNull(insnNode);
      
          int idx = insnList.indexOf(insnNode);
          Validate.isTrue(idx != -1);
      
          // Get index of labels and insnNode within method
          ListIterator<AbstractInsnNode> insnIt = insnList.iterator(idx);
          while (insnIt.hasPrevious()) {
              AbstractInsnNode node = insnIt.previous();
      
              if (node instanceof LineNumberNode) {
                  return (LineNumberNode) node;
              }
          }
      
          return null;
      

      }

      【讨论】:

      • 感谢您的回答。正如@Holger 所说,问题无法解决,但你给出了有用的例子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-27
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 2017-12-24
      • 1970-01-01
      相关资源
      最近更新 更多