1. 程式人生 > 其它 >Java效能調優工具:Jstack

Java效能調優工具:Jstack

1.命令說明

Jstack是Jdk自帶的執行緒跟蹤工具,用於列印指定Java程序的執行緒堆疊資訊。

2.引數說明

jstack -l [pid]

  

注意:windows環境只支援這麼一個引數

3.使用示例

jstack -l 5524 > c:\users\Administrator\Desktop\jstack.txt

2018-09-14 12:59:46
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.77-b03 mixed mode):
"ActiveMQ InactivityMonitor Worker" #528 daemon prio=5 os_prio=0 tid=0x000000001ce03800 nid=0x1bc8 waiting on condition [0x000000003dadf000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x000000071cf5ea58> (a java.util.concurrent.SynchronousQueue$TransferStack)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
	at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
	at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
   Locked ownable synchronizers:
	- None
"ActiveMQ InactivityMonitor Worker" #527 daemon prio=5 os_prio=0 tid=0x000000001ce05800 nid=0x22c8 waiting on condition [0x000000003f56e000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x000000071cf5ea58> (a java.util.concurrent.SynchronousQueue$TransferStack)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
	at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
	at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
	at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
   Locked ownable synchronizers:
	- None
.........

  

java命令–jstack 工具

執行緒狀態

想要通過jstack命令來分析執行緒的情況的話,首先要知道執行緒都有哪些狀態,下面這些狀態是我們使用jstack命令檢視執行緒堆疊資訊時可能會看到的執行緒的幾種狀態:

NEW:未啟動的。不會出現在Dump中。

RUNNABLE:在虛擬機器內執行的。執行中狀態,可能裡面還能看到locked字樣,表明它獲得了某把鎖。

BLOCKED:受阻塞並等待監視器鎖。被某個鎖(synchronizers)給block住了。

WATING:無限期等待另一個執行緒執行特定操作。等待某個condition或monitor發生,一般停留在park(), wait(), sleep(),join() 等語句裡。

TIMED_WATING:有時限的等待另一個執行緒的特定操作。和WAITING的區別是wait() 等語句加上了時間限制 wait(timeout)。

TERMINATED:已退出的。

Monitor

在多執行緒的 JAVA程式中,實現執行緒之間的同步,就要說說 Monitor。 Monitor是 Java中用以實現執行緒之間的互斥與協作的主要手段,它可以看成是物件或者 Class的鎖。每一個物件都有,也僅有一個 monitor。下 面這個圖,描述了執行緒和 Monitor之間關係,以 及執行緒的狀態轉換圖:

進入區(Entrt Set):表示執行緒通過synchronized要求獲取物件的鎖。如果物件未被鎖住,則迚入擁有者;否則則在進入區等待。一旦物件鎖被其他執行緒釋放,立即參與競爭。

擁有者(The Owner):表示某一執行緒成功競爭到物件鎖。

等待區(Wait Set) :表示執行緒通過物件的wait方法,釋放物件的鎖,並在等待區等待被喚醒。

從圖中可以看出,一個 Monitor在某個時刻,只能被一個執行緒擁有,該執行緒就是 “Active Thread”,而其它執行緒都是 “Waiting Thread”,分別在兩個佇列 “ Entry Set”和 “Wait Set”裡面等候。在 “Entry Set”中等待的執行緒狀態是 “Waiting for monitor entry”,而在“Wait Set”中等待的執行緒狀態是 “in Object.wait()”。 先看 “Entry Set”裡面的執行緒。我們稱被 synchronized保護起來的程式碼段為臨界區。當一個執行緒申請進入臨界區時,它就進入了 “Entry Set”佇列。對應的 code就像:

synchronized(obj) {
.........
}

  

呼叫修飾

表示執行緒在方法呼叫時,額外的重要的操作。執行緒Dump分析的重要資訊。修飾上方的方法呼叫。

locked <地址> 目標:使用synchronized申請物件鎖成功,監視器的擁有者。

waiting to lock <地址> 目標:使用synchronized申請物件鎖未成功,在迚入區等待。

waiting on <地址> 目標:使用synchronized申請物件鎖成功後,釋放鎖幵在等待區等待。

parking to wait for <地址> 目標 :需與堆疊中的"parking to wait for (atjava.util.concurrent.SynchronousQueue$TransferStack)"結合來看。first–>此執行緒是在等待某個條件的發生,來把自己喚醒,second–>SynchronousQueue不是一個佇列,其是執行緒之間移交資訊的機制,當我們把一個元素放入到 SynchronousQueue 中時必須有另一個執行緒正在等待接受移交的任務,因此這就是本執行緒在等待的條件。

locked

at oracle.jdbc.driver.PhysicalConnection.prepareStatement
- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.PhysicalConnection.prepareStatement
- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)
at com.jiuqi.dna.core.internal.db.datasource.PooledConnection.prepareStatement

  

通過synchronized關鍵字,成功獲取到了物件的鎖,成為監視器的擁有者,在臨界區內操作。物件鎖是可以執行緒重入的。

waiting to lock

at com.jiuqi.dna.core.impl.CacheHolder.isVisibleIn(CacheHolder.java:165)
- waiting to lock <0x0000000097ba9aa8> (a CacheHolder)
at com.jiuqi.dna.core.impl.CacheGroup$Index.findHolder
at com.jiuqi.dna.core.impl.ContextImpl.find
at com.jiuqi.dna.bap.basedata.common.util.BaseDataCenter.findInfo

  

通過synchronized關鍵字,沒有獲取到了物件的鎖,執行緒在監視器的進入區等待。在呼叫棧頂出現,執行緒狀態為Blocked。

waiting on

at java.lang.Object.wait(Native Method)
- waiting on <0x00000000da2defb0> (a WorkingThread)
at com.jiuqi.dna.core.impl.WorkingManager.getWorkToDo
- locked <0x00000000da2defb0> (a WorkingThread)
at com.jiuqi.dna.core.impl.WorkingThread.run

  

通過synchronized關鍵字,成功獲取到了物件的鎖後,呼叫了wait方法,進入物件的等待區等待。在呼叫棧頂出現,執行緒狀態為WAITING或TIMED_WATING。

parking to wait for

park是基本的執行緒阻塞原語,不通過監視器在物件上阻塞。隨concurrent包會出現的新的機制,不synchronized體系不同。

runnable:狀態一般為RUNNABLE。
in Object.wait():等待區等待,狀態為WAITING或TIMED_WAITING。
waiting for monitor entry:進入區等待,狀態為BLOCKED。
waiting on condition:等待區等待、被park。
sleeping:休眠的執行緒,呼叫了Thread.sleep()。

  

執行緒動作

執行緒狀態產生的原因

Wait on condition 該狀態出現線上程等待某個條件的發生。具體是什麼原因,可以結合 stacktrace來分析。 最常見的情況就是執行緒處於sleep狀態,等待被喚醒。 常見的情況還有等待網路IO:在java引入nio之前,對於每個網路連線,都有一個對應的執行緒來處理網路的讀寫操作,即使沒有可讀寫的資料,執行緒仍然阻塞在讀寫操作上,這樣有可能造成資源浪費,而且給作業系統的執行緒排程也帶來壓力。在 NewIO裡採用了新的機制,編寫的伺服器程式的效能和可擴充套件性都得到提高。 正等待網路讀寫,這可能是一個網路瓶頸的徵兆。因為網路阻塞導致執行緒無法執行。一種情況是網路非常忙,幾 乎消耗了所有的頻寬,仍然有大量資料等待網路讀 寫;另一種情況也可能是網路空閒,但由於路由等問題,導致包無法正常的到達。所以要結合系統的一些效能觀察工具來綜合分析,比如 netstat統計單位時間的傳送包的數目,如果很明顯超過了所在網路頻寬的限制 ; 觀察 cpu的利用率,如果系統態的 CPU時間,相對於使用者態的 CPU時間比例較高;如果程式執行在 Solaris 10平臺上,可以用 dtrace工具看系統呼叫的情況,如果觀察到 read/write的系統呼叫的次數或者執行時間遙遙領先;這些都指向由於網路頻寬所限導致的網路瓶頸。(來自http://www.blogjava.net/jzone/articles/303979.html)

4.Windows上如何檢視耗CPU最高的執行緒

使用windows工具ProcessExplorer來獲取對應的執行緒資訊

windows下揪出java程式佔用cpu很高的執行緒 並找到問題程式碼 死迴圈執行緒程式碼

5.Linux上如何檢視耗CPU最高的執行緒

這個由於不想安裝Linux虛擬機器整環境了,請需要的同學直接非同步下面連結

JVM調優之jstack找出最耗cpu的執行緒並定位程式碼

以上就是關於“Java效能調優工具:Jstack”的介紹