jstack

jstack命令主要用于調(diào)試java程序運行過程中的線程堆棧信息蠕啄,可以用于檢測死鎖,進程耗用cpu過高報警問題的排查馅巷。

jstack語法格式:

[root@www wangxiaoxiao]# jstack

Usage:
    jstack [-l] <pid>
    jstack -F [-m] [-l] <pid>

Options:
    -F  強制dump線程堆棧信息. 用于進程hung住急前, jstack <pid>命令沒有響應(yīng)的情況
    -m  同時打印java和本地(native)線程棧信息狈网,m是mixed mode的簡寫
    -l  打印鎖的額外信息

jstack命令會打印出所有的線程礼搁,包括用戶自己啟動的線程和jvm后臺線程,我們主要關(guān)注的是用戶線程目尖,如

[root@www wangxiaoxiao]# jstack 15525
2017-02-14 21:10:02
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.65-b01 mixed mode):
**"elasticsearch[Native][merge][T#1]" **#98** daemon prio=5 os_prio=0 tid=0x00007f031c009000 nid=0x4129 waiting on condition [0x00007f02f61ee000]**
   **java.lang.Thread.State: WAITING (parking)**
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000000eea589f0> (a org.elasticsearch.common.util.concurrent.EsExecutors$ExecutorScalingQueue)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.LinkedTransferQueue.awaitMatch(LinkedTransferQueue.java:737)
    at java.util.concurrent.LinkedTransferQueue.xfer(LinkedTransferQueue.java:647)
    at java.util.concurrent.LinkedTransferQueue.take(LinkedTransferQueue.java:1269)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
    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)
....

線程dump信息說明:
elasticsearch[Native][merge][T#1] 是我們?yōu)榫€程起的名字
**daemon **表示線程是否是守護線程
**prio **表示我們?yōu)榫€程設(shè)置的優(yōu)先級
**os_prio **表示的對應(yīng)的操作系統(tǒng)線程的優(yōu)先級馒吴,由于并不是所有的操作系統(tǒng)都支持線程優(yōu)先級,所以可能會出現(xiàn)都置為0的情況
**tid **是java中為這個線程的id
**nid **是這個線程對應(yīng)的操作系統(tǒng)本地線程id瑟曲,每一個java線程都有一個對應(yīng)的操作系統(tǒng)線程
wait on condition表示當(dāng)前線程處于等待狀態(tài)饮戳,但是并沒列出具體原因
java.lang.Thread.State: WAITING (parking) 也是表示的處于等待狀態(tài),括號中的內(nèi)容說明了導(dǎo)致等待的原因洞拨,例如這里的parking說明是因為調(diào)用了 LockSupport.park方法導(dǎo)致等待

java.lang.Thread.State說明:
一個Thread對象可以有多個狀態(tài)扯罐,在java.lang.Thread.State中,總共定義六種狀態(tài):

1烦衣、NEW

線程剛剛被創(chuàng)建歹河,也就是已經(jīng)new過了,但是還沒有調(diào)用start()方法花吟,jstack命令不會列出處于此狀態(tài)的線程信息

2秸歧、RUNNABLE #java.lang.Thread.State: RUNNABLE

RUNNABLE這個名字很具有欺騙性,很容易讓人誤以為處于這個狀態(tài)的線程正在運行衅澈。事實上键菱,這個狀態(tài)只是表示,線程是可運行的今布。我們已經(jīng)無數(shù)次提到過经备,一個單核CPU在同一時刻拭抬,只能運行一個線程。

3侵蒙、BLOCKED # java.lang.Thread.State: BLOCKED (on object monitor)

線程處于阻塞狀態(tài)造虎,正在等待一個monitor lock。通常情況下蘑志,是因為本線程與其他線程公用了一個鎖累奈。其他在線程正在使用這個鎖進入某個synchronized同步方法塊或者方法,而本線程進入這個同步代碼塊也需要這個鎖急但,最終導(dǎo)致本線程處于阻塞狀態(tài)澎媒。

4、WAITING

等待狀態(tài)波桩,調(diào)用以下方法可能會導(dǎo)致一個線程處于等待狀態(tài):

  • Object.wait 不指定超時時間 # java.lang.Thread.State: WAITING (on object monitor)
  • [Thread.join] with no timeout
  • [LockSupport.park]#java.lang.Thread.State: WAITING (parking)

例如:對于wait()方法戒努,一個線程處于等待狀態(tài),通常是在等待其他線程完成某個操作镐躲。本線程調(diào)用某個對象的wait()方法储玫,其他線程處于完成之后,調(diào)用同一個對象的notify或者notifyAll()方法萤皂。Object.wait()方法只能夠在同步代碼塊中調(diào)用撒穷。調(diào)用了wait()方法后,會釋放鎖裆熙。

5端礼、TIMED_WAITING

線程等待指定的時間,對于以下方法的調(diào)用入录,可能會導(dǎo)致線程處于這個狀態(tài):

  • [Thread.sleep] #java.lang.Thread.State: TIMED_WAITING(sleeping)
  • [Object.wait] 指定超時時間 #java.lang.Thread.State: TIMED_WAITING (on object monitor)
  • [Thread.join] with timeout
  • [LockSupport.parkNanos] #java.lang.Thread.State: TIMED_WAITING (parking)
  • [LockSupport.parkUntil] #java.lang.Thread.State: TIMED_WAITING (parking)

6蛤奥、TERMINATED

線程終止。

說明僚稿,對于** java.lang.Thread.State: WAITING (on object monitor)java.lang.Thread.State: TIMED_WAITING (on object monitor)**凡桥,對于這兩個狀態(tài),是因為調(diào)用了Object的wait方法(前者沒有指定超時蚀同,后者指定了超時)缅刽,由于wait方法肯定要在syncronized代碼中編寫,因此肯定是如類似以下代碼導(dǎo)致:

synchronized(obj) {
    .........
    obj.wait();
    .........
}

因此通常的堆棧信息中蠢络,必然后一個lock標(biāo)記拷恨,如下:

"CM1" #21 daemon prio=5 os_prio=0 tid=0x00007f02f0d6d800 nid=0x3d48 in Object.wait() [0x00007f02fefef000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:502)
        at java.util.TimerThread.mainLoop(Timer.java:526)
       ** - locked <0x00000000eca75aa8> (a java.util.TaskQueue)**
        at java.util.TimerThread.run(Timer.java:505)

關(guān)于死鎖

在 JAVA 5中加強了對死鎖的檢測。線程 Dump中可以直接報告出 Java級別的死鎖谢肾,如下所示:

**Found one Java-level deadlock:**
=============================
"Thread-1":
waiting to lock monitor 0x0003f334 (object 0x22c19f18, a java.lang.Object),
which is held by "Thread-0"
"Thread-0":
waiting to lock monitor 0x0003f314 (object 0x22c19f20, a java.lang.Object),
which is held by "Thread-1"

關(guān)于nid

每個線程都有一個tid 和nid腕侄,tid是java中這個線程的編號,而nid(native id)是對應(yīng)操作系統(tǒng)線程id。有的時候冕杠,我們會收到報警微姊,說服務(wù)器,某個進程占用CPU過高分预,肯定是因為某個java線程有耗CPU資源的方法兢交。

可以通過命令cat /proc/<pid>/task查看一個進程下面有哪些線程

可以通過"top -Hp"命令查看這個進程內(nèi)所有線程的cpu和內(nèi)容使用情況使用情況:

上例中看到12446進程中,12467線程占用cpu最高笼痹,是0.3%配喳。要想看這個線程對應(yīng)java哪個線程,首先用以下命令將12467轉(zhuǎn)成16進制:

接著使用jstack命令凳干,顯示堆棧信息:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晴裹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子救赐,更是在濱河造成了極大的恐慌涧团,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件经磅,死亡現(xiàn)場離奇詭異泌绣,居然都是意外死亡,警方通過查閱死者的電腦和手機预厌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門阿迈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人轧叽,你說我怎么就攤上這事仿滔。” “怎么了犹芹?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鞠绰。 經(jīng)常有香客問我腰埂,道長,這世上最難降的妖魔是什么蜈膨? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任屿笼,我火速辦了婚禮,結(jié)果婚禮上翁巍,老公的妹妹穿的比我還像新娘驴一。我一直安慰自己,他們只是感情好灶壶,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布肝断。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胸懈。 梳的紋絲不亂的頭發(fā)上担扑,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音趣钱,去河邊找鬼涌献。 笑死,一個胖子當(dāng)著我的面吹牛首有,可吹牛的內(nèi)容都是我干的燕垃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼井联,長吁一口氣:“原來是場噩夢啊……” “哼卜壕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起低矮,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤印叁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后军掂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轮蜕,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年蝗锥,在試婚紗的時候發(fā)現(xiàn)自己被綠了跃洛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡终议,死狀恐怖汇竭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情穴张,我是刑警寧澤细燎,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站皂甘,受9級特大地震影響玻驻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜偿枕,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一璧瞬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渐夸,春花似錦嗤锉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奥额。三九已至,卻和暖如春酷誓,著一層夾襖步出監(jiān)牢的瞬間披坏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工盐数, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留棒拂,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓玫氢,卻偏偏與公主長得像帚屉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子漾峡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容

  • jstack命令的用法為jstack pid jstack在jdk/bin的目錄下 在實際運行中攻旦,建議產(chǎn)生3次以上...
    better0812閱讀 8,877評論 0 0
  • jstack用于打印出給定的java進程ID或core file或遠程調(diào)試服務(wù)的Java堆棧信息,如果是在64位機...
    sherlock_6981閱讀 944評論 0 0
  • (文章內(nèi)容部分來源自于網(wǎng)絡(luò)生逸,如有侵權(quán)牢屋,請告知刪除) 前言 去年負(fù)責(zé)的一個項目老出現(xiàn)線程阻塞,線上三天兩頭服務(wù)內(nèi)存溢...
    不加糖的開水閱讀 1,002評論 0 0
  • 一槽袄、命令介紹 jstack是jdk自帶的jvm分析工具烙无,用于打印指定 java進程,core文件 或者遠程 調(diào)試服...
    理查德成閱讀 2,738評論 2 2
  • jstack簡介 通過jstack,我們可以輕松得知jvm中各個線程的工作情況. 工作情況 jstack -l p...
    黃二的NPE閱讀 8,584評論 0 4