1. 程式人生 > >Linux下Java執行緒詳細監控和其dump的分析使用----分析Java效能瓶頸[張振華-Jack]

Linux下Java執行緒詳細監控和其dump的分析使用----分析Java效能瓶頸[張振華-Jack]



作者:張振華(Jack)
這裡對linux下、sun(oracle) JDK的執行緒資源佔用問題的查詢步驟做一個小結;
linux環境下,當發現java程序佔用CPU資源很高,且又要想更進一步查出哪一個java執行緒佔用了CPU資源時,按照以下步驟進行查詢: (一):通過【top -p 12377 -H】 檢視java程序的有哪些執行緒的執行情況;       和通過【jstack 12377 > stack.log】生成Java執行緒的dump詳細資訊;
    1. 先用top命令找出佔用資源厲害的java程序id,如圖:# top
    2. 如上圖所示,java的程序id為'52554',接下來用top命令單獨對這個程序中的所有執行緒作監視:
  1. 1 top -p 52554 -H

    #  top視圖裡面裡面可以通過快捷鍵依次b ,x高亮顯示top的列找出需要的執行緒,預設CPU排序,Shift+< ,Shift+>可以左右移動高亮排序的列;
    如圖:(這時就看出來哪個java執行緒CPU高,哪個執行緒記憶體用的多)

  2. 如上圖所示,linux下,所有的java內部執行緒,其實都對應了一個程序id,也就是說,linux上的sun jvm將java程式中的執行緒對映為了作業系統程序;我們看到,佔用CPU資源最高的那個程序id是'15417',這個程序id對應java執行緒資訊中的'nid'('n' stands for 'native');
  3. (1)要想找到到底是哪段具體的程式碼佔用瞭如此多的資源,先使用jstack打出當前棧資訊到一個檔案裡, 比如stack.log:
    1
    jstack 52554 > stack.log
    然後使用'jtgrep'指令碼把這個程序號為'9757'的java執行緒在stack.log中抓出來:
    1 jtgrep 9757 stack.log

    其中,'jtgrep'是自己隨便寫的一個shell指令碼:

    1 #!/bin/sh
    3 nid=`python -c "print hex($1)"`
    4 grep -i $nid $2

    道理很簡單,就是把'9757'轉換成16進位制後,直接grep stack.log;可以看到,被grep出的那個執行緒的nid=0x3c39,正好是15417的16進製表示。

(2) 通過(windows程式-->計算器),選擇程式設計師計算器將程序ID轉換成16進位制 到dump裡面的nid就可以搜尋到
"http-nio-8080-exec-25" daemon prio=10 tid=0x00007f69686b4800 nid=0x1ce5 waiting on condition [0x00007f698e7cf000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0000000777063ec8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(Unknown Source)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
        at java.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
        at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
(二)第二種通過Java visualMv結合jconsole.exe 工具即可檢視如圖所示;(第一種方式可能更準確一些)



三:在Java Visualvm工具裡面安裝JTA外掛,分析執行緒dump檔案,注意,正常階段的dump檔案與非正常時期的Dump檔案進行比較更容易分析出問題: (1)下載:https://java.net/projects/tda/downloads/directory/visualvm   (2)安裝與使用: (3)使用:


四:直接通過tda-bin-2.2\bin\tda.sh 來分析匯出ThreadDump檔案;(在沒有JMX監控的情況下手動檢視threadDump資訊)        下載地址:https://java.net/projects/tda/downloads/directory/visualvm