如何在Java中跟踪方法调用?
考虑下面的两个简单的Java类:
第一个例子
class Computer { Computer() { System.out.println("Constructor of Computer class."); } void On() { System.out.println("PC turning on..."); } void working() { System.out.println("PC working..."); } void Off() { System.out.println("PC shuting down..."); } public static void main(String[] args) { Computer my = new Computer(); Laptop your = new Laptop(); my.On(); my.working(); your.On(); your.working(); my.Off(); your.Off(); } }
第二个例子
class Laptop { Laptop() { System.out.println("Constructor of Laptop class."); } void On() { System.out.println("Laptop turning on..."); } void working() { System.out.println("Laptop working..."); } void Off() { System.out.println("Laptop shuting down..."); } }
程序运行后,如何跟踪(1)哪个对象调用哪个方法(2)和多少次?
只需要一点精度,我可能有100个类和1000个对象,每个对象调用100个方法。 我希望能够跟踪(在我运行程序之后),哪个对象调用哪个方法和多少次。
谢谢你的任何建议。
这将为所有线程中的所有对象的每个方法调用打印一行:
Runtime.traceMethodCalls()(Java 9中已弃用/无操作)
和
Runtime.traceInstructions(Java 9中已弃用/无操作)
您可以使用像housemd或btrace或inTrace这样的呼叫跟踪器
对于更复杂的分析,您可以使用调用图实用程序,如下所示:
-
javashot
-
Java的调用图
(这是一篇关于这个主题的文章 )
上面已弃用的方法将被删除,因为现在有特定于JVM的替代方法:
- Java Flight Recorder 从构建版本56开始的JDK 7的一部分。需要商业许可证才能在生产中使用
- VisualVM 免费/流行的第三方
这两个工具都很容易设置并开始收集信息并具有良好的GUI界面。 它们附加到正在运行的JVM进程并允许线程快照和各种其他类型的诊断(Visual VM有很多可用的插件,但如果你想超越默认行为,可能需要一段时间才能进行排序以进行配置和理解,而JFR默认配备更多)。
此外,不要低估JVM分布式命令行实用程序( $JAVA_HOME/bin
)的有用性,以执行一些易于访问的诊断。
- jstack 堆栈跟踪
- jmap 内存映射
- jstat JVM统计监控
- jhat 堆分析工具
- jdb 调试器
- jinfo java进程或核心文件配置信息
$ jdb -classpath ... -sourcepath ... my.App jdb> stop on my.App.main jdb> run jdb> step <... repeat until get to interesting line...> jdb> threads jdb> trace go methods 0x1 <... 0x1 is our main thread ID ...> jdb> step <...HERE you get full methods calls trace...> jdb> quit