jstack

jstack是java虛擬機自帶的一種堆疊跟蹤工具。

基本介紹

  • 中文名:java虛擬機堆疊跟蹤工具
  • 外文名:jstack
基本介紹,命令格式,案例,說明,死鎖,原始碼,分析和結果,

基本介紹

jstack用於生成java虛擬機當前時刻的執行緒快照。執行緒快照是當前java虛擬機內每一條執行緒正在執行的方法堆疊的集合,生成執行緒快照的主要目的是定位執行緒出現長時間停頓的原因,如執行緒間死鎖、死循環、請求外部資源導致的長時間等待等。
執行緒出現停頓的時候通過jstack來查看各個執行緒的調用堆疊,就可以知道沒有回響的執行緒到底在後台做什麼事情,或者等待什麼資源。

命令格式

jstack [ option ] pid
基本參數:
-F 當’jstack [-l] pid’沒有回響的時候強制列印棧信息
-l 長列表. 列印關於鎖的附加信息,例如屬於java.util.concurrent的ownable synchronizers列表.
-m 列印java和native c/c++框架的所有棧信息. -h | -help列印幫助信息
pid 需要被列印配置信息的java進程id,可以用jps工具查詢.

案例

說明

  1. 不同的 JAVA虛機的執行緒 DUMP的創建方法和檔案格式是不一樣的,不同的 JVM版本, dump信息也有差別。
  2. 在實際運行中,往往一次 dump的信息,還不足以確認問題。建議產生三次 dump信息,如果每次 dump都指向同一個問題,我們才確定問題的典型性。

死鎖

在多執行緒程式的編寫中,如果不適當的運用同步機制,則有可能造成程式的死鎖,經常表現為程式的停頓,或者不再回響用戶的請求。比如在下面這個示例中,是個較為典型的死鎖情況:
dump結果
  1. "Thread-1"prio=5tid=0x00acc490nid=0xe50waitingformonitorentry[0x02d3f000
  2. ..0x02d3fd68]
  3. atdeadlockthreads.TestThread.run(TestThread.java:31)
  4. -waitingtolock<0x22c19f18>(ajava.lang.Object)
  5. -locked<0x22c19f20>(ajava.lang.Object)
  6. "Thread-0"prio=5tid=0x00accdb0nid=0xdecwaitingformonitorentry[0x02cff000
  7. ..0x02cff9e8]
  8. atdeadlockthreads.TestThread.run(TestThread.java:31)
  9. -waitingtolock<0x22c19f20>(ajava.lang.Object)
  10. -locked<0x22c19f18>(ajava.lang.Object)
在 JAVA 5中加強了對死鎖的檢測。執行緒 Dump中可以直接報告出 Java級別的死鎖,如下所示:
dump結果
  1. FoundoneJava-leveldeadlock:
  2. =============================
  3. "Thread-1":
  4. waitingtolockmonitor0x0003f334(object0x22c19f18,ajava.lang.Object),
  5. whichisheldby"Thread-0"
  6. "Thread-0":
  7. waitingtolockmonitor0x0003f314(object0x22c19f20,ajava.lang.Object),
  8. whichisheldby"Thread-1"

原始碼

package com.jdkTools;
/**
*簡單的套用,供測試JDK自帶的jstack使用 本套用會造成deadlock,可能會導致系統崩潰
*邏輯:一旦兩個執行緒互相等待的局面出現,死鎖(deadlock)就發生了
*
* @author范芳銘
*/
public class EasyJstack extends Thread {
private EasyJstackResourceresourceManger;//資源管理類的私有引用,通過此引用可以通過其相關接口對資源進行讀寫
private int a, b;//將要寫入資源的數據
public static void main(String[]args) throws Exception {
EasyJstackResourceresourceManager = new EasyJstackResource();
EasyJstack stack1 = newEasyJstack(resourceManager, 1, 2);
EasyJstack stack2 = newEasyJstack(resourceManager, 3, 4);
stack1.start();
stack2.start();
}
publicEasyJstack(EasyJstackResource resourceManager, int a, int b) {
this.resourceManger =resourceManager;
this.a = a;
this.b = b;
}
public void run() {
while (true) {
this.resourceManger.read();
this.resourceManger.write(this.a,this.b);
}
}
}
package com.jdkTools;
/**
* @author范芳銘
*/
public class EasyJstackResource {
/**
*管理的兩個資源,如果有多個執行緒並發,那么就會死鎖
*/
private Resource resourceA = newResource();
private Resource resourceB = newResource();
public EasyJstackResource() {
this.resourceA.setValue(0);
this.resourceB.setValue(0);
}
public int read() {
synchronized (this.resourceA){
System.out.println(Thread.currentThread().getName()
+ "執行緒拿到了資源 resourceA的對象鎖");
synchronized (resourceB){
System.out.println(Thread.currentThread().getName()
+ "執行緒拿到了資源 resourceB的對象鎖");
return this.resourceA.getValue()+ this.resourceB.getValue();
}
}
}
public void write(int a, int b) {
synchronized (this.resourceB){
System.out.println(Thread.currentThread().getName()
+ "執行緒拿到了資源 resourceB的對象鎖");
synchronized(this.resourceA) {
System.out.println(Thread.currentThread().getName()
+ "執行緒拿到了資源 resourceA的對象鎖");
this.resourceA.setValue(a);
this.resourceB.setValue(b);
}
}
}
public class Resource {
private int value;//資源的屬性
public int getValue() {
return value;
}
public void setValue(intvalue) {
this.value = value;
}
}
}

分析和結果

Java stack information for the threads listed above:
===================================================
"Thread-1":
atcom.jdkTools.EasyJstackResource.read(EasyJstackResource.java:27)
- waitingto lock <0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)
- locked<0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)
atcom.jdkTools.EasyJstack.run(EasyJstack.java:34)
"Thread-0":
atcom.jdkTools.EasyJstackResource.write(EasyJstackResource.java:42)
- waitingto lock <0x03b8ed30> (a com.jdkTools.EasyJstackResource$Resource)
- locked<0x03b8ed40> (a com.jdkTools.EasyJstackResource$Resource)
atcom.jdkTools.EasyJstack.run(EasyJstack.java:35)
Found 1 deadlock.
仔細看這一段文字,告訴我們 EasyJstackResource.java:27出了狀況。如果出現了這種情況,我們就要從這裡開始順藤摸瓜,解決問題。

熱門詞條

聯絡我們