最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM之jstack命令的使用解讀

 更新時間:2025年07月19日 09:55:46   作者:AiFlutter  
jstack是Java線程分析工具,用于生成線程快照,排查死鎖和CPU過高問題,通過參數(shù)如-F、-l獲取線程狀態(tài)及鎖信息,解析Monitor機制與線程阻塞原因(如網(wǎng)絡(luò)瓶頸、sleep狀態(tài)),幫助定位性能問題

一、簡介

jstack全稱叫Java Stack Trace,Java的堆棧跟蹤工具,用于生成java虛擬機當前時刻的線程快照。

功能主要有兩個如下

  • 分析死鎖;
  • 分析CPU過高問題。

1.1 命令格式

  • jstack [ option ] pid 查看當前時間點,指定進程的dump堆棧信息。
  • jstack [ option ] pid > 文件 將當前時間點的指定進程的dump堆棧信息,寫入到指定文件中。# 注:若該文件不存在,則會自動生成; 若該文件存在,則會覆蓋源文件。
  • jstack [ option ] executable core 查看當前時間點,core文件的dump堆棧信息。
  • jstack [ option ] [server_id@]<remote server IP or hostname> 查看當前時間點,遠程機器的dump堆棧信息。

option 參數(shù)如下:

名稱

說明

-F當正常輸出的請求不被響應(yīng)時,強制輸出線程堆棧。

-m

 打印java和native c/c++框架的所有棧信息??梢源蛴VM的堆棧,以及Native的棧幀,一般應(yīng)用排查不需要使用。
-l除堆棧外,顯示關(guān)于鎖的附加信息,在發(fā)生死鎖時可以用jstack -l pid來觀察鎖持有情況。

1.2 獲取CPU飆高的線程id

1.2.1 找到CPU飆高的進程

獲取各個進程的CPU和內(nèi)存情況,并且找到CPU飆高的進程ID,比如進程ID=10843

  • top

1.2.2 顯示java進程的CPU和內(nèi)存占用情況

  • top -p 進程id

1.2.3 獲取每個線程的CPU和內(nèi)存占用情況

  • 按H

1.2.4 jstack查看線程情況

# 將10進制線程id轉(zhuǎn)為16進制

printf "%x\n" 線程id

# 查看線程情況

jstack 進程ID | grep -A 10  十六進制的線程ID

二、jstack輸出內(nèi)容解析

其中標注daemon字樣的是后臺線程。

用戶線程中包括:

  1. 線程的一些基本信息:名稱、優(yōu)先級及id
  2. 線程狀態(tài):waiting on condition等
  3. 線程的調(diào)用棧
  4. 線程鎖住的資源:locked<0x3f63d600>

2.1 Monitor(監(jiān)視器)

在多線程的java程序中,實現(xiàn)線程之間的同步,就要說說Monitor。

Monitor是java中用以實現(xiàn)線程之間的互斥與協(xié)作的主要手段,它可以看成是對象或者Class的鎖。每一個對象都有,也僅有一個Monitor。

  1. 進入?yún)^(qū)(Entry Set):表示線程通過synchronized要求獲取對象的鎖。如果對象未被鎖住,則進入擁有者;否則在進入?yún)^(qū)等待。一旦對象鎖被其他線程釋放,立即參與競爭。
  2. 擁有者(The Owner):表示某一線程成功競爭到對象鎖。
  3. 等待區(qū)(Wait Set):表示線程通過對象的wait方法釋放對象的鎖,并在等待區(qū)等待被喚醒。

一個 Monitor在某個時刻,只能被一個線程擁有,該線程就是 “Active Thread”,而其它線程都是 “Waiting Thread”,分別在兩個隊列 “ Entry Set”和 “Wait Set”里面等候。

在 “Entry Set”中等待的線程狀態(tài)是 “Waiting for monitor entry”,而在“Wait Set”中等待的線程狀態(tài)是 “in Object.wait()”。

先看 “Entry Set”里面的線程。我們稱被 synchronized保護起來的代碼段為臨界區(qū)。當一個線程申請進入臨界區(qū)時,它就進入了 “Entry Set”隊列。對應(yīng)的 code就像:

synchronized(obj){
        ……
}

2.2 調(diào)用修飾

表示線程在方法調(diào)用時額外的重要操作。線程dump分析的重要信息。修飾上方的方法調(diào)用。

  1. locked<地址>目標:使用synchronized申請對象鎖成功,監(jiān)視器的擁有者;
  2. waiting to lock<地址>目標:使用synchronized申請對象鎖未成功,在進入?yún)^(qū)等待;
  3. waiting on<地址>目標:使用synchronized申請對象鎖成功后,調(diào)用了wait方法,進入對象的等待區(qū)等待。在調(diào)用棧頂出線,線程狀態(tài)為WAITING或TIMED_WAITING;
  4. parking to wait for<地址>目標:park是基本的線程阻塞原語,不通過監(jiān)視器在對象上阻塞。隨concurrent包出現(xiàn)的新的機制,與synchronized體系不同。

2.3 線程狀態(tài)

  • 死鎖,Deadlock(重點關(guān)注)
  • 等待資源,Waiting on condition(重點關(guān)注)
  • 等待獲取管程,Waiting on monitor entry(點關(guān)注)
  • 阻塞,Blocked(重點關(guān)注)
  • 執(zhí)行中,Runnable
  • 暫停,Suspended
  • 對象等待中,Object.wait() 或 TIMED_WAITING
  • 停止,Parked

輸出信息例如

"Thread-1" prio=10 tid=0x08223860 nid=0xa waiting on condition [0xef47a000..0xef47ac38] 
         at java.lang.Thread.sleep(Native Method) 
         at testthread.MySleepingThread.method2(MySleepingThread.java:53) 
         - locked <0xef63d600> (a testthread.MySleepingThread) 
         at testthread.MySleepingThread.run(MySleepingThread.java:35) 
         at java.lang.Thread.run(Thread.java:595) </span>

我們能看到:

  • 線程的狀態(tài): waiting on condition
  • 線程的調(diào)用棧
  • 線程的當前鎖住的資源: <0xef63d600>

Wait on condition

該狀態(tài)出現(xiàn)在線程等待某個條件的發(fā)生。具體是什么原因,可以結(jié)合 stacktrace來分析。最常見的情況是線程在等待網(wǎng)絡(luò)的讀寫,比如當網(wǎng)絡(luò)數(shù)據(jù)沒有準備好讀時,線程處于這種等待狀態(tài),而一旦有數(shù)據(jù)準備好讀之后,線程會重新激活,讀取并處理數(shù)據(jù)。在 Java引入 NewIO之前,對于每個網(wǎng)絡(luò)連接,都有一個對應(yīng)的線程來處理網(wǎng)絡(luò)的讀寫操作,即使沒有可讀寫的數(shù)據(jù),線程仍然阻塞在讀寫操作上,這樣有可能造成資源浪費,而且給操作系統(tǒng)的線程調(diào)度也帶來壓力。在 NewIO里采用了新的機制,編寫的服務(wù)器程序的性能和可擴展性都得到提高。

如果發(fā)現(xiàn)有大量的線程都在處在 Wait on condition,從線程 stack看, 正等待網(wǎng)絡(luò)讀寫,這可能是一個網(wǎng)絡(luò)瓶頸的征兆。因為網(wǎng)絡(luò)阻塞導(dǎo)致線程無法執(zhí)行。一種情況是網(wǎng)絡(luò)非常忙,幾 乎消耗了所有的帶寬,仍然有大量數(shù)據(jù)等待網(wǎng)絡(luò)讀 寫;另一種情況也可能是網(wǎng)絡(luò)空閑,但由于路由等問題,導(dǎo)致包無法正常的到達。所以要結(jié)合系統(tǒng)的一些性能觀察工具來綜合分析,比如 netstat統(tǒng)計單位時間的發(fā)送包的數(shù)目,如果很明顯超過了所在網(wǎng)絡(luò)帶寬的限制 ; 觀察 cpu的利用率,如果系統(tǒng)態(tài)的 CPU時間,相對于用戶態(tài)的 CPU時間比例較高;如果程序運行在 Solaris 10平臺上,可以用 dtrace工具看系統(tǒng)調(diào)用的情況,如果觀察到 read/write的系統(tǒng)調(diào)用的次數(shù)或者運行時間遙遙領(lǐng)先;這些都指向由于網(wǎng)絡(luò)帶寬所限導(dǎo)致的網(wǎng)絡(luò)瓶頸。另外一種出現(xiàn) Wait on condition的常見情況是該線程在 sleep,等待 sleep的時間到了時候,將被喚醒。

Waiting for monitor entry 和 in Object.wait()

在多線程的 JAVA程序中,實現(xiàn)線程之間的同步,就要說說 Monitor。 Monitor是 Java中用以實現(xiàn)線程之間的互斥與協(xié)作的主要手段,它可以看成是對象或者 Class的鎖。每一個對象都有,也僅有一個 monitor。每個 Monitor在某個時刻,只能被一個線程擁有,該線程就是 “Active Thread”,而其它線程都是 “Waiting Thread”,分別在兩個隊列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的線程狀態(tài)是 “Waiting for monitor entry”,而在 “Wait Set”中等待的線程狀態(tài)是 “in Object.wait()”。

先看 “Entry Set”里面的線程。我們稱被 synchronized保護起來的代碼段為臨界區(qū)。當一個線程申請進入臨界區(qū)時,它就進入了 “Entry Set”隊列。

這時有兩種可能性:

1、該 monitor不被其它線程擁有, Entry Set里面也沒有其它等待線程。本線程即成為相應(yīng)類或者對象的 Monitor的 Owner,執(zhí)行臨界區(qū)的代碼

2、該 monitor被其它線程擁有,本線程在 Entry Set隊列中等待。

在第一種情況下,線程將處于 “Runnable”的狀態(tài),而第二種情況下,線程 DUMP會顯示處于 “waiting for monitor entry”。

臨界區(qū)的設(shè)置,是為了保證其內(nèi)部的代碼執(zhí)行的原子性和完整性。但是因為臨界區(qū)在任何時間只允許線程串行通過,這 和我們多線程的程序的初衷是相反的。 如果在多線程的程序中,大量使用 synchronized,或者不適當?shù)氖褂昧怂?,會造成大量線程在臨界區(qū)的入口等待,造成系統(tǒng)的性能大幅下降。如果在線程 DUMP中發(fā)現(xiàn)了這個情況,應(yīng)該審查源碼,改進程序。

現(xiàn)在我們再來看現(xiàn)在線程為什么會進入 “Wait Set”。當線程獲得了 Monitor,進入了臨界區(qū)之后,如果發(fā)現(xiàn)線程繼續(xù)運行的條件沒有滿足,它則調(diào)用對象(一般就是被 synchronized 的對象)的 wait() 方法,放棄了 Monitor,進入 “Wait Set”隊列。只有當別的線程在該對象上調(diào)用了 notify() 或者 notifyAll() , “ Wait Set”隊列中線程才得到機會去競爭,但是只有一個線程獲得對象的 Monitor,恢復(fù)到運行態(tài)。

在 “Wait Set”中的線程, DUMP中表現(xiàn)為: in Object.wait(),類似于:仔細觀察上面的 DUMP信息,你會發(fā)現(xiàn)它有以下兩行:

  • - locked <0xef63beb8> (a java.util.ArrayList)
  • - waiting on <0xef63beb8> (a java.util.ArrayList)

線程的執(zhí)行中,先用 synchronized 獲得了這個對象的 Monitor(對應(yīng)于 locked <0xef63beb8> )。當執(zhí)行到 obj.wait(), 線程即放棄了 Monitor的所有權(quán),進入 “wait set”隊列(對應(yīng)于 waiting on <0xef63beb8> )。

往往在你的程序中,會出現(xiàn)多個類似的線程,他們都有相似的 DUMP信息。這也可能是正常的。比如,在程序中,有多個服務(wù)線程,設(shè)計成從一個隊列里面讀取請求數(shù)據(jù)。這個隊列就是 lock以及 waiting on的對象。

當隊列為空的時候,這些線程都會在這個隊列上等待,直到隊列有了數(shù)據(jù),這些線程被 Notify,當然只有一個線程獲得了 lock,繼續(xù)執(zhí)行,而其它線程繼續(xù)等待。

2.4 線程動作

線程狀態(tài)產(chǎn)生的原因:

  • runnable:狀態(tài)一般為RUNNABLE,表示線程具備所有運行條件,在運行隊列中準備操作系統(tǒng)的調(diào)度,或者正在運行。
  • in Object.wait():等待區(qū)等待,狀態(tài)為WAITING或TIMED_WAITING。
  • waiting for monitor entry:進入?yún)^(qū)等待,狀態(tài)為BLOCKED。
  • waiting on condition:等待去等待,被park。
  • sleeping:休眠的線程,調(diào)用了Thread.sleep()。

Wait on condition 該狀態(tài)出現(xiàn)在線程等待某個條件的發(fā)生。具體是什么原因,可以結(jié)合 stacktrace來分析。 最常見的情況就是線程處于sleep狀態(tài),等待被喚醒。 常見的情況還有等待網(wǎng)絡(luò)IO:在java引入nio之前,對于每個網(wǎng)絡(luò)連接,都有一個對應(yīng)的線程來處理網(wǎng)絡(luò)的讀寫操作,即使沒有可讀寫的數(shù)據(jù),線程仍然阻塞在讀寫操作上,這樣有可能造成資源浪費,而且給操作系統(tǒng)的線程調(diào)度也帶來壓力。

在 NIO里采用了新的機制,編寫的服務(wù)器程序的性能和可擴展性都得到提高。 正等待網(wǎng)絡(luò)讀寫,這可能是一個網(wǎng)絡(luò)瓶頸的征兆。因為網(wǎng)絡(luò)阻塞導(dǎo)致線程無法執(zhí)行。一種情況是網(wǎng)絡(luò)非常忙,幾 乎消耗了所有的帶寬,仍然有大量數(shù)據(jù)等待網(wǎng)絡(luò)讀 寫;另一種情況也可能是網(wǎng)絡(luò)空閑,但由于路由等問題,導(dǎo)致包無法正常的到達。所以要結(jié)合系統(tǒng)的一些性能觀察工具來綜合分析,比如 netstat統(tǒng)計單位時間的發(fā)送包的數(shù)目,如果很明顯超過了所在網(wǎng)絡(luò)帶寬的限制 ; 觀察 cpu的利用率,如果系統(tǒng)態(tài)的 CPU時間,相對于用戶態(tài)的 CPU時間比例較高;如果程序運行在 Solaris 10平臺上,可以用 dtrace工具看系統(tǒng)調(diào)用的情況,如果觀察到 read/write的系統(tǒng)調(diào)用的次數(shù)或者運行時間遙遙領(lǐng)先;這些都指向由于網(wǎng)絡(luò)帶寬所限導(dǎo)致的網(wǎng)絡(luò)瓶頸。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Linux上兩種網(wǎng)絡(luò)連接實現(xiàn)方式

    Linux上兩種網(wǎng)絡(luò)連接實現(xiàn)方式

    這篇文章主要介紹了Linux上兩種網(wǎng)絡(luò)連接實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Linux(Ubuntu 18.04)上安裝Anaconda步驟詳解

    Linux(Ubuntu 18.04)上安裝Anaconda步驟詳解

    Anaconda是最受歡迎的python數(shù)據(jù)科學(xué)和機器學(xué)習(xí)平臺,用于大規(guī)模數(shù)據(jù)處理,預(yù)測分析和科學(xué)計算。這篇文章主要介紹了Linux(Ubuntu 18.04)上安裝Anaconda的方法,需要的朋友可以參考下
    2018-11-11
  • centos中yum命令刪除還原的補救方法介紹

    centos中yum命令刪除還原的補救方法介紹

    Yum: 即Yellowdog Update Modifier,是一種基于rpm的包管理工具,這篇文章主要給大家介紹了關(guān)于在centos中yum命令刪除還原的補救方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Linux之TCP網(wǎng)絡(luò)套接字詳解

    Linux之TCP網(wǎng)絡(luò)套接字詳解

    TCP socket API包含創(chuàng)建、綁定、監(jiān)聽、接受連接、連接等步驟,需三次握手建立連接,四次揮手斷開,與UDP相比,TCP是面向連接的可靠傳輸協(xié)議,基于字節(jié)流進行數(shù)據(jù)交換,確保雙向通信可靠性
    2025-08-08
  • 在CentOS 7上設(shè)置靜態(tài)IP地址的詳細指南

    在CentOS 7上設(shè)置靜態(tài)IP地址的詳細指南

    配置靜態(tài)IP地址是服務(wù)器或虛擬機管理的重要步驟之一,特別是在需要穩(wěn)定、可預(yù)測的網(wǎng)絡(luò)環(huán)境時,本文將詳細介紹如何在CentOS 7上設(shè)置靜態(tài)IP地址,幫助確保你的系統(tǒng)網(wǎng)絡(luò)配置符合需求,需要的朋友可以參考下
    2025-09-09
  • 簡單架設(shè)SSH+Squid代理服務(wù)器的自由上網(wǎng)通道的方法

    簡單架設(shè)SSH+Squid代理服務(wù)器的自由上網(wǎng)通道的方法

    Squid是一個高性能的代理緩存服務(wù)器,但缺點是網(wǎng)址是以明文的形式發(fā)送的。在我們的特殊互聯(lián)網(wǎng)環(huán)境中,就算使用這樣的代理服務(wù)器,打開網(wǎng)頁時也常常會被“Reset”。
    2011-03-03
  • Apache 解決80端口占用問題

    Apache 解決80端口占用問題

    今天小編發(fā)現(xiàn)一個很棘手的問題,在安裝mongodb后發(fā)現(xiàn)apache無法啟動問題,今天小編給大家?guī)砹薃pache 解決80端口占用問題 ,感興趣的朋友一起看看吧
    2018-03-03
  • linux環(huán)境下安裝jdk和Tomcat詳細步驟

    linux環(huán)境下安裝jdk和Tomcat詳細步驟

    大家好,本篇文章主要講的是linux環(huán)境下安裝jdk和Tomcat詳細步驟,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收一下,方便下次瀏覽
    2021-12-12
  • Ubuntu系統(tǒng)中查看網(wǎng)絡(luò)速率的幾種方法

    Ubuntu系統(tǒng)中查看網(wǎng)絡(luò)速率的幾種方法

    這篇文章主要給大家介紹了在 Ubuntu系統(tǒng)中,可以使用以下幾種方法查看網(wǎng)絡(luò)速率,文中通過代碼示例講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-11-11
  • Linux通過匿名管道進行進程間通信

    Linux通過匿名管道進行進程間通信

    這篇文章主要介紹了Linux通過匿名管道進行進程間通信,介紹了什么是管道,popen函數(shù),pipe調(diào)用等相關(guān)內(nèi)容,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01

最新評論

陆良县| 武定县| 兴安盟| 广汉市| 苍山县| 丹东市| 屏边| 博爱县| 博爱县| 昭苏县| 黄冈市| 嫩江县| 巴青县| 台南市| 平阴县| 杭锦后旗| 磐石市| 慈溪市| 永胜县| 吉木乃县| 牙克石市| 蒙城县| 凤山县| 甘孜| 旬阳县| 闻喜县| 徐水县| 根河市| 精河县| 黔南| 达拉特旗| 阜阳市| 崇明县| 花莲县| 康乐县| 尚义县| 西乡县| 罗山县| 巢湖市| 新平| 沈阳市|