– Java 堆內存分解; 從HotSpot VM 1.6版本開始,在線程堆棧的末尾處能夠看到HotSpot的內存使用狀況,好比說Java的堆內存(YoungGen, OldGen) & PermGen 空間。這個信息對分析因爲頻繁GC而引發的問題時,是頗有用的。你可使用已知的線程數據或模式作一個快速的定位。
Heap
PSYoungGen total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000)
eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000)
from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000)
to space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000)
PSOldGen total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000)
object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000)
PSPermGen total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000)
object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee0400000)
線程堆棧信息大拆解
爲了讓你們更好的理解,給你們提供了下面的這張圖,在這張圖中將HotSpot VM上的線程堆棧信息和線程池作了詳細的拆解,以下圖所示:
上圖中能夠看出線程堆棧是由多個不一樣部分組成的。這些信息對問題分析都很重要,但對不一樣的問題模式的分析會使用不一樣的部分(問題模式會在後面的文章中作模擬和演示。)
如今經過這個分析樣例,給你們詳細解釋一下HoteSpot上線程堆棧信息中的各個組成部分:
# Full thread dump標示符
「Full thread dump」是一個全局惟一的關鍵字,你能夠在中間件和單機版本Java的線程堆棧信息的輸出日誌中找到它(好比說在UNIX下使用:kill -3 <PID> )。這是線程堆棧快照的開始部分。
Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.0-b11 mixed mode):
# Java EE 中間件,第三方以及自定義應用軟件中的線程
這個部分是整個線程堆棧的核心部分,也是一般須要花費最多分析時間的部分。堆棧中線程的個數取決你使用的中間件,第三方庫(可能會有獨立線程)以及你的應用程序(若是建立自定義線程,這一般不是一個很好的實踐)。
在咱們的示例線程堆棧中,WebLogic是咱們所使用的中間件。從Weblogic 9.2開始, 會使用一個用「’weblogic.kernel.Default (self-tuning)」惟一標識的能自行管理的線程池
"[STANDBY] ExecuteThread: '414' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=3 tid=0x000000010916a800 nid=0x2613 in Object.wait() [0xfffffffe9edff000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0xffffffff27d44de0> (a weblogic.work.ExecuteThread) at java.lang.Object.wait(Object.java:485) at weblogic.work.ExecuteThread.waitForRequest(ExecuteThread.java:160) - locked <0xffffffff27d44de0> (a weblogic.work.ExecuteThread) at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)
# HotSpot VM 線程
這是一個有Hotspot VM管理的內部線程,用於執行內部的原生操做。通常你不用對此操太多心,除非你(經過相關的線程堆棧以及 prstat或者原生線程Id)發現很高的CPU佔用率.
"VM Periodic Task Thread" prio=3 tid=0x0000000101238800 nid=0x19 waiting on condition
# HotSpot GC 線程
當使用 HotSpot 進行並行 GC (現在在使用多個物理核心的環境下很常見), 默認建立的HotSpot VM 或者每一個JVM管理一個有特定標識的GC線程時. 這些GC線程可讓VM以並行的方式執行其週期性的GC清理, 這會致使GC時間的整體減小;與此同時的代價是CPU的使用時間會增長.
"GC task thread#0 (ParallelGC)" prio=3 tid=0x0000000100120000 nid=0x3 runnable
"GC task thread#1 (ParallelGC)" prio=3 tid=0x0000000100131000 nid=0x4 runnable ………………………………………………………………………………………………………………………………………………………………
這事很是關鍵的數據,由於當你遇到跟GC有關的問題,諸如過分GC、內存泄露等問題是,你將能夠利用這些線程的原生Id值關聯的操做系統或者Java線程,進而發現任何對CPI時間的高佔用. 將來的文章你將會了解到如何識別並診斷這樣的問題.
# JNI 全局引用計數
JNI (Java 本地接口)的全局引用就是從本地代碼到由Java垃圾收集器管理的Java對象的基本的對象引用. 它的角色就是阻止對仍然在被本地代碼使用,可是技術上已經不是Java代碼中的「活動的」引用了的對象的垃圾收集.
同時爲了偵測JNI相關的泄露而留意JNI引用也很重要. 若是你的程序直接使用了JNI,或者像監聽器這樣的第三方工具,就容易形成本地的內存泄露.
JNI global references: 1925
# Java 堆棧使用視圖
這些數據被添加回了 JDK 1 .6 ,向你提供有關Hotspot堆棧的一個簡短而快速的視圖. 我發現它在當我處理帶有太高CPU佔用的GC相關的問題時很是有用,你能夠在一個單獨的快照中同時看到線程堆棧以及Java堆的信息,讓你當時就能夠在一個特定的Java堆內存空間中解析(或者排除)出任何的關鍵點. 你如在咱們的示例線程堆棧中所見,Java 的堆 OldGen 超出了最大值!
Heap
PSYoungGen total 466944K, used 178734K [0xffffffff45c00000, 0xffffffff70800000, 0xffffffff70800000)
eden space 233472K, 76% used [0xffffffff45c00000,0xffffffff50ab7c50,0xffffffff54000000)
from space 233472K, 0% used [0xffffffff62400000,0xffffffff62400000,0xffffffff70800000)
to space 233472K, 0% used [0xffffffff54000000,0xffffffff54000000,0xffffffff62400000)
PSOldGen total 1400832K, used 1400831K [0xfffffffef0400000, 0xffffffff45c00000, 0xffffffff45c00000)
object space 1400832K, 99% used [0xfffffffef0400000,0xffffffff45bfffb8,0xffffffff45c00000)
PSPermGen total 262144K, used 248475K [0xfffffffed0400000, 0xfffffffee0400000, 0xfffffffef0400000)
object space 262144K, 94% used [0xfffffffed0400000,0xfffffffedf6a6f08,0xfffffffee0400000)
我但願這篇文章能對你理解Hotspot VM線程堆棧的基本信息有所幫助。下一篇文章將會向你提供有關IBM VM的線程堆棧概述和分析.
請自由的向本文發表觀點或疑問.
引用: 如何分析線程堆棧 —— 第一部分, 如何分析線程堆棧——第二部分 & 如何分析線程堆棧——第三部分 來自咱們的 Java EE Support Patterns & Java Tutorial 博客上的 JCG 合做者Hugues Charbonneau.