如何在Java源文件中获取给定行号的周围方法

我有一个Java源文件的行号,并希望以编程方式获取该行号的搜索方法。

我查看了ANTLR ,这对我没什么帮助。

Janino( http://www.janino.net )似乎很有希望,我会扫描并解析(如果需要,编译)代码。 然后我可以使用JDI和

ReferenceType.locationsOfLine(int lineNumber) 

我仍然不知道如何使用JDI来做这件事,并没有找到这方面的任何教程。

也许还有一些我完全失踪的方式。

如果您使用的是Java 6,并且不介意使用Sun的API,则可以使用javac API 。 您需要将tools.jar添加到类路径中。

 import java.io.IOException; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import javax.tools.JavaCompiler.CompilationTask; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.LineMap; import com.sun.source.tree.MethodTree; import com.sun.source.util.JavacTask; import com.sun.source.util.SourcePositions; import com.sun.source.util.TreeScanner; import com.sun.source.util.Trees; public class MethodFinder { public static void main(String[] args) { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector diagnosticsCollector = new DiagnosticCollector(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnosticsCollector, null, null); Iterable fileObjects = fileManager.getJavaFileObjects("path/to/Source.java"); CompilationTask task = compiler.getTask(null, fileManager, diagnosticsCollector, null, null, fileObjects); // Here we switch to Sun-specific APIs JavacTask javacTask = (JavacTask) task; SourcePositions sourcePositions = Trees.instance(javacTask).getSourcePositions(); Iterable parseResult = null; try { parseResult = javacTask.parse(); } catch (IOException e) { // Parsing failed e.printStackTrace(); System.exit(0); } for (CompilationUnitTree compilationUnitTree : parseResult) { compilationUnitTree.accept(new MethodLineLogger(compilationUnitTree, sourcePositions), null); } } private static class MethodLineLogger extends TreeScanner { private final CompilationUnitTree compilationUnitTree; private final SourcePositions sourcePositions; private final LineMap lineMap; private MethodLineLogger(CompilationUnitTree compilationUnitTree, SourcePositions sourcePositions) { this.compilationUnitTree = compilationUnitTree; this.sourcePositions = sourcePositions; this.lineMap = compilationUnitTree.getLineMap(); } @Override public Void visitMethod(MethodTree arg0, Void arg1) { long startPosition = sourcePositions.getStartPosition(compilationUnitTree, arg0); long startLine = lineMap.getLineNumber(startPosition); long endPosition = sourcePositions.getEndPosition(compilationUnitTree, arg0); long endLine = lineMap.getLineNumber(endPosition); // Voila! System.out.println("Found method " + arg0.getName() + " from line " + startLine + " to line " + endLine + "."); return super.visitMethod(arg0, arg1); } } } 

您可以使用ASM的CodeVisitor从已编译的类中检索调试行信息 。 这样可以节省Java源文件的解析。

 ClassReader reader = new ClassReader(A.class.getName()); reader.accept(new ClassVisitor() { public CodeVisitor visitMethod(int access, String name, String desc, String[] exceptions, Attribute attrs) { System.out.println(name); return new CodeVisitor() { public void visitLineNumber(int line, Label start) { System.out.println(line); } } } }, false); 

对于A类:

 11 class A { 12 13 public void x() { 14 int x = 1; 15 System.out.println("Hello"); 16 } 17 18 public void y() { 19 System.out.println("World!"); 20 } 21 } 

这会产生:

  11 x 14 15 16 y 19 20 

如果您在运行时需要此信息。 您可以创建一个exception并查看堆栈跟踪元素 。

也许你可以抛出一个exception,抓住它,提取相应的stacktrace元素来获取方法名称。