如何跟蹤java程式碼的執行
阿新 • • 發佈:2019-01-01
當我們的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等,非常方便。