jstack+jdb命令查看線程及死鎖堆棧信息


如果程序掛死,有時使用jstack查看進程中線程信息時,需要添加上-F參數,此時如果有死鎖信息,則可能不會打印出死鎖堆棧信息,使用jdb則可以查看當前死鎖線程的運行堆棧。

如下模擬一個簡單的死鎖程序

package com.demo.bootdemo;

import java.util.HashMap;
import java.util.Map;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class MyListeners implements ApplicationListener<ContextRefreshedEvent> {

    private Map map = new HashMap<>();
    private String lock = "aa";

    @Override
    public void onApplicationEvent(ContextRefreshedEvent arg0) {

        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (map) {
                    System.out.println(Thread.currentThread().getName() + ": 獲得map鎖");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    synchronized (lock) {
                        System.out.println(Thread.currentThread().getName() + ": 獲得lock鎖");    
                    }
                }
            }
        }, "t-1");

        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() + ": 獲得lock鎖");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    synchronized (map) {
                        System.out.println(Thread.currentThread().getName() + ": 獲得map鎖");    
                    }
                }
            }
        }, "t-2");
        
        t.start();
        t2.start();
    }

}

獲取pid

假設當前不能直接連接27709虛擬機,需要使用參數-F

可以看出造成死鎖的線程未t-1和t-2

使用jdb連接jvm

jdb -connect sun.jvm.hotspot.jdi.SAPIDAttachingConnector:pid=27709

執行threads命令獲取所有線程列表

獲取線程“t-1”堆棧信息,如下圖,結合上述模擬死鎖的代碼,很容易就能看出來是哪里的問題

類似的,獲取線程“t-2”的堆棧信息

通過以上步驟,基本上可以確定問題代碼了。

本例也是匆忙中簡單查看了下文檔,沒有詳看,后續有時間在進行補充,jdb文檔如下

https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr011.html#BABDHAHJ

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM