JVM之jstack的使用


簡介: 

  有些時候我們需要查看下jvm中的線程執行情況,比如,發現服務器的CPU的負載突然增高了、出現了死鎖、死循環等,我們該如何分析呢?

由於程序是正常運行的,沒有任何的輸出,從日志方面也看不出什么問題,所以就需要看下jvm的內部線程的執行情況,然后再進行分析查找出原因。

這個時候,就需要借助於jstack命令了,jstack的作用是將正在運行的jvm的線程情況進行快照,並且打印出來;

在Java中線程的狀態一共被分成6種:

  初始狀態:New,線程對象創建出來后,沒有調用start方法,線程處於初始狀態
  運行狀態:包含了就緒狀態和運行狀態
    1.就緒狀態:Ready,調用了Start方法,等待CPU分配資源
    2.運行狀態:RUNNING,CPU分配資源給該線程,該線程處於運行狀態
  阻塞狀態 BLOCKED:
      線程獲取資源,如果資源獲取成功則正常運行,如果資源獲取失敗,就處於阻塞狀態,等待什么時候獲取到資源再變為運行狀態
  等待狀態 WAITING:線程手動調用了wait()方法,或者join()方法,這些方法都是主動進入等待狀態,等待狀態會將CPU資源讓渡
      需要其他線程手動喚醒,notify(),notifyAll()喚起所有的等待線程
  超時等待狀態 TIMED_WAITING:與等待狀態相同,都是主動進入等待,也是需要其他線程喚醒,但是區別在與超時等待,如果超過了等待時間,則自動喚醒
      Thread.sleep(2000),在休眠等待時間內會將CPU資源讓渡,然后等待時間結束自動進入運行狀態
  終止狀態 DIED:線程結束之后的狀態

案例:解決死鎖問題

  如果在生產環境發生了死鎖,我們將看到的是部署的程序沒有任何反應了,這個時候我們可以借助jstack進行分析,下面我們實戰下查找死鎖的原因。

構建死鎖

  編寫代碼,啟動2個線程,Thread1拿到了obj1鎖,准備去拿obj2鎖時,obj2已經被Thread2鎖定,所以發送了死鎖。

public class LockTest {
    //定義資源
    private static Object obj1=new Object();
    private static Object obj2=new Object();
    //線程A:先獲取到資源1,然后休眠2s,再獲取資源2
    private static class ThreadA implements Runnable {
        @Override
        public void run() {
            synchronized (obj1) {
                System.out.println("ThreadA獲取到了OBJ1資源");

                try {
                    //休眠2s,因為我們要將CPU資源讓渡出去,這樣線程B就可以先搶占obj2資源
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (obj2) {
                    System.out.println("ThreadA獲取到了OBJ2資源");
                }
            }
        }
    }
    private static class ThreadB implements Runnable{
        @Override
        public void run() {
            synchronized (obj2){
                System.out.println("ThreadB獲取到了OBJ2資源");

                try {
                    //休眠2s,因為我們要將CPU資源讓渡出去,這樣線程B就可以先搶占obj2資源
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                synchronized (obj1){
                    System.out.println("ThreadA獲取到了OBJ1資源");
                }
            }
        }
    }

    public static void main(String[] args) {
        new Thread(new ThreadA()).start();
        new Thread(new ThreadB()).start();
    }
}

  運行出現死鎖問題

   檢查狀態

   查看線程運行情況

   主要看如下:

   在輸出的信息中,已經看到,發現了1個死鎖

  可以清晰的看到:

    Thread-1獲取了 <0x0517c5b0> 的鎖,等待獲取 <0x0517c5a8>這個鎖

    Thread-0獲取了 <0x0517c5a8> 的鎖,等待獲取 <0x0517c5b0>這個鎖

  由此可見,發生了死鎖


免責聲明!

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



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