如何在 Java 中跟踪方法调用?

2022-09-03 05:54:48

考虑下面两个简单的 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个方法。我希望能够跟踪(在我运行程序后),哪个对象调用了哪个方法以及多少次。

感谢您的任何建议。


答案 1

这将为所有线程中所有对象的每个方法调用打印一行:

Runtime.traceMethodCalls() (deprecated / no-op in Java 9)

Runtime.traceInstructions (deprecated / no-op in Java 9)

您可以使用调用跟踪程序,如 housemdbtraceinTrace

对于更复杂的分析,您可以使用呼叫图实用程序,例如:

(这是一篇关于这个主题的文章)

上面不推荐使用的方法将被删除,因为现在有特定于JVM的替代方法:

  • Java Flight Recorder 是 JDK 7 的一部分,自 build 56 起。需要商业许可证才能在生产中使用
  • VisualVM 免费/流行的第三方

这两个工具都很容易设置并开始收集信息,并且具有漂亮的GUI界面。它们附加到正在运行的JVM进程,并允许线程快照和各种其他类型的诊断(Visual VM有很多可用的插件,但如果你想超越默认行为,可能需要一段时间来排序来配置和理解,而JFR在默认情况下是用更多来检测的)。

另外,不要低估JVM分布式命令行实用程序()的有用性,用于执行一些易于访问的诊断。$JAVA_HOME/bin

  • jstack 堆栈跟踪
  • jmap 内存映射
  • jstat JVM 统计监控
  • jhat 堆分析工具
  • jdb 调试器
  • jinfo        java process or core file config info

答案 2
$ 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