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

如何在Java中跟踪方法调用?,java,methods,call,trace,Java,Methods,Call,Trace,考虑下面两个简单的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 work

考虑下面两个简单的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...");
    }
}
第二个示例

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中已弃用/无操作)

您可以使用呼叫跟踪器,如

对于更复杂的分析,您可以使用调用图实用程序,如以下工具之一:

(这是一份关于这个问题的报告)

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

  • JDK 7的一部分,从构建56开始。需要商业许可证才能用于生产
  • 免费/受欢迎的第三方
这两种工具都非常容易设置和开始收集信息,并且具有良好的GUI界面。它们连接到一个正在运行的JVM进程,并允许线程快照和各种其他类型的诊断(VisualVM有很多可用的插件,但如果您想超越默认行为,则可能需要一段时间进行排序以进行配置和理解,而JFR在默认情况下使用了更多插件)

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

  • 堆栈跟踪
  • 内存映射
  • JVM统计信息监视
  • 堆分析工具
  • 调试器
  • java进程或核心文件配置信息
$jdb-classpath-源路径。。。我的.App
jdb>在my.App.main上停止
jdb>运行
jdb>步骤
jdb>线程
jdb>跟踪go方法0x1
jdb>步骤
jdb>退出

您是否询问更复杂或更一般的示例?从这个例子来看,这是显而易见的,因为每个类只有一个实例,并且没有继承。@DanielNugent我正在寻找一个在任何情况下都可以使用的答案。我可能有100个类和1000个对象调用每100个方法。我希望能够跟踪(在运行程序之后),哪个对象调用了哪个方法以及调用了多少次。谢谢-George@1sand0s谢谢,我是新来的。我可能不太理解代码的格式。@1sand0s我刚做了格式设置,现在看起来还可以。感谢您留下4个空格的提示。请注意,这个方法以及
traceInstructions()
是从Java 9开始的。另外,请注意,这些方法不仅被弃用,而且也变成了不可操作的方法,因此用户在迁移到JDK 9时应该寻找替代方法。注意,
traceInstructions()
似乎很少起作用,即使使用旧的JVM。我试了几次(6、7、8),但都没有成功。这与许多其他报告相匹配,例如:
重复直到到达感兴趣的行
这一部分的答案是假的。
$ 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