如何跟踪java代码的执行

来源:互联网 发布:win10 grub引导ubuntu 编辑:程序博客网 时间:2024/04/28 16:38

当我们的java程序在执行时阻塞了,或是运行时越来越慢,我们如何定位代码的问题?

在C中可以通过strace来跟踪代码的函数调用过程,在调试代码时十分方便。在java中,也有对应的工具。这里提供2种用来跟踪java代码执行的方法。

jmap

通过该命令捕获镜像,再通过其他命令来查看。
总的来说是两步:
(1) 就是通过jmap命令来获取hprof文件
(2) 通过工具来查看该文件的函数调用栈

生成hprof文件

jmap -dump:file=/tmp/heap.hprof $PID

查看hprof文件

查看hprof文件可以使用以下工具:MemoryAnalyzer

MemoryAnalyzer的操作步骤

overview -> Leak Suspects -> Table Of Contents -> Thread Overview -> main -> list objects -> with outgoing references

在这个页面中可以看到类和函数的调用过程。
函数是从上到下的调用。

jstack

注意: 该命令无法使用使用root来执行。

shell> jstack 7340

这里的7340是运行zookeeper的进程号。

以下是通过命令jstack观察zookeeper的输出得到的类和函数调用栈:

... "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f23ac07f000 nid=0x1d0f in Object.wait() [0x00007f239c3b0000]   java.lang.Thread.State: WAITING (on object monitor)    at java.lang.Object.wait(Native Method)    - waiting on <0x000000076f386b40> (a java.lang.ref.Reference$Lock)    at java.lang.Object.wait(Object.java:502)    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)    - locked <0x000000076f386b40> (a java.lang.ref.Reference$Lock)    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)"main" #1 prio=5 os_prio=0 tid=0x00007f23ac009000 nid=0x1d09 in Object.wait() [0x00007f23b5470000]   java.lang.Thread.State: WAITING (on object monitor)    at java.lang.Object.wait(Native Method)    - waiting on <0x000000076fbb90c8> (a org.apache.zookeeper.server.quorum.QuorumPeer)    at java.lang.Thread.join(Thread.java:1249)    - locked <0x000000076fbb90c8> (a org.apache.zookeeper.server.quorum.QuorumPeer)    at java.lang.Thread.join(Thread.java:1323)    at org.apache.zookeeper.server.quorum.QuorumPeerMain.runFromConfig(QuorumPeerMain.java:171)    at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:114)    at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:81)...

通过以上的输出,可以清楚的看到zookeeper的执行过程,这对于调试大型的软件比如hadoop等,非常方便。