我需要使用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来解决这个问题?
以下代码段给出了相同的结果,第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;
}
答案 0 :(得分:1)
任何字节码处理库提供的行号都基于LineNumberTable
attribute,它将方法的可执行指令映射到行号。所以这是一个基本的限制,你不能在类文件中找到不会导致生成可执行字节代码的源代码行。
有时甚至取决于编译器,跨越多行的构造的源代码行被分配给。
答案 1 :(得分:0)
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;
}