如何在 Java 中跟踪方法调用?
Posted
技术标签:
【中文标题】如何在 Java 中跟踪方法调用?【英文标题】:How do I trace methods calls in Java? 【发布时间】:2015-06-05 14:16:26 【问题描述】:考虑以下两个简单的 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 个方法。我希望能够跟踪(在我运行程序之后),哪个对象调用了哪个方法以及调用了多少次。
感谢您的任何建议。
【问题讨论】:
您是在询问更复杂或更一般的示例吗?从这个例子中,很明显,因为每个类只有一个实例,并且没有继承。 @DanielNugent 我正在寻找可在任何情况下使用的答案。我可能有 100 个类和 1000 个对象调用每 100 个方法。我希望能够跟踪(在我运行程序之后),哪个对象调用了哪个方法以及多少次。谢谢 - 乔治 @1sand0s 谢谢,我是新来的。我可能对代码格式不太了解。 @1sand0s 我刚刚进行了格式化,现在看起来没问题。感谢您留下 4 个空格的提示。 【参考方案1】:这会为所有线程中所有对象的每个方法调用打印一行:
Runtime.traceMethodCalls()(Java 9 中已弃用/无操作)
和
Runtime.traceInstructions(Java 9 中已弃用/无操作)
您可以使用呼叫跟踪器,如 housemd 或 btrace 或 inTrace
对于更复杂的分析,您可以使用如下调用图实用程序之一:
javashot
java-callgraph
(这里有一个关于主题的article)
上述不推荐使用的方法将被删除,因为现在有特定于 JVM 的替代方法:
Java Flight Recorder JDK 7 自 build 56 的一部分。需要商业许可才能在生产中使用 VisualVM 免费/受欢迎的第三者这两个工具都非常易于设置和开始收集信息,并且具有漂亮的 GUI 界面。它们附加到正在运行的 JVM 进程,并允许线程快照和各种其他类型的诊断(Visual VM 有很多可用的插件,但如果你想超越默认行为,可能需要一段时间来配置和理解,而JFR 默认配备更多)。
此外,不要低估 JVM 分布式命令行实用程序 ($JAVA_HOME/bin
) 的实用性,它可以执行一些易于访问的诊断。
【讨论】:
请注意,从 Java 9 开始,此方法与traceInstructions()
一起是 deprecated。
另外,请注意,这些方法不仅已被弃用,而且也变成了无操作,因此用户在迁移到 JDK 9 时应该寻找替代方法。
注意,traceInstructions()
似乎很少工作,即使是旧的 JVM。我尝试了几个(6、7、8),但无济于事。这与许多其他报告相匹配,例如:***.com/a/1025685/7256341【参考方案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
【讨论】:
这个答案的repeat until get to interesting line
部分使它成为假的。以上是关于如何在 Java 中跟踪方法调用?的主要内容,如果未能解决你的问题,请参考以下文章
java是不是有任何机制让VM在不使用javaagent等的情况下跟踪自身的方法调用?