java線程堆棧_深入JVM剖析Java的線程堆棧

在這篇文章里我將教會你如何分析JVM的線程堆棧以及如何從堆棧信息中找出問題的根因。在我看來線程堆棧分析技術是Java EE產品支持工程師所必須掌握的一門技術。在線程堆棧中存儲的信息,通常遠超出你的想象,我們可以在工作中善加利用這些信息。

我的目標是分享我過去十幾年來在線程分析中積累的知識和經驗。這些知識和經驗是在各種版本的JVM以及各廠商的JVM供應商的深入分析中獲得的,在這個過程中我也總結出大量的通用問題模板。

那么,準備好了么,現在就把這篇文章加入書簽,在后續幾周中我會給大家帶來這一系列的專題文章。還等什么,請趕緊給你的同事和朋友分享這個線程分析培訓計劃吧。

聽上去是不錯,我確實是應該提升我的線程堆棧分析技能...但我要從哪里開始呢?

我的建議是跟隨我來完成這個線程分析培訓計劃。下面是我們會覆蓋到的培訓內容。同時,我會把我處理過的實際案例分享給大家,以便與大家學習和理解。

1) 線程堆棧概述及基礎知識

2) 線程堆棧的生成原理以及相關工具

3) 不同JVM線程堆棧的格式的差異(Sun HotSpot、IBM JRE、Oracal JRockit)

4) 線程堆棧日志介紹以及解析方法

5) 線程堆棧的分析和相關的技術

6) 常見的問題模板(線程竟態、死鎖、IO調用掛死、垃圾回收/OutOfMemoryError問題、死循環等)

7) 線程堆棧問題實例分析

我希望這一系列的培訓能給你帶來確實的幫助,所以請持續關注每周的文章更新。

但是如果我在學習過程中有疑問或者無法理解文章中的內容該怎么辦?

不用擔心,把我當做你的導師就好。任何關于線程堆棧的問題都可以咨詢我(前提是問題不能太low)。請隨意選擇下面的幾種方式與我取得聯系:

1) 直接本文下面發表評論(不好意思的話可以匿名)

2) 將你的線程堆棧數據提交到Root Cause Analysis forum

3) 發Email給我,地址是 @phcharbonneau@hotmail.com

能幫我分析我們產品上遇到的問題么?

當然可以,如果你愿意的話可以把你的堆棧現場數據通過郵件或論壇 Root Cause Analysis forum發給我。處理實際問題是才是學習提升技能的王道。

我真心期望大家能夠喜歡這個培訓。所以我會盡我所能去為你提供高質量的材料,并回答大家的各種問題。

在介紹線程堆棧分析技術和問題模式之前,先要給大家講講基礎的內容。所以在這篇帖子里,我將先覆蓋到最基本的內容,這樣大家就能更好的去理解JVM、中間件、以及Java EE容器之間的交互。

Java VM 概述

Java虛擬機是Jave EE 平臺的基礎。它是中間件和應用程序被部署和運行的地方。

JVM向中間件軟件和你的Java/Java EE程序提供了下面這些東西:

–?? (二進制形式的)Java / Java EE 程序運行環境

–?? 一些程序功能特性和工具 (IO 基礎設施,數據結構,線程管理,安全,監控 等等.)

–?? 借助垃圾回收的動態內存分配與管理

你的JVM可以駐留在許多的操作系統 (Solaris, AIX, Windows 等等.)之上,并且能根據你的物理服務器配置,你可以在每臺物理/虛擬服務器上安裝1到多個JVM進程.

JVM與中間件之間的交互

下面這張圖展示了JVM、中間件和應用程序之間的高層交互模型。

07adbbfe0c821fe9418385352f6418f4.png

圖中展示的JVM、中間件和應用程序件之間的一些簡單和典型的交互。如你所見,標準Java EE應用程序的線程的分配實在中間件內核與JVM之間完成的。(當然也有例外,應用程序可以直接調用API來創建線程,這種做法并不常見,而且在使用的過程中也要特別的小心)

同時,請注意一些線程是由JVM內部來進行管理的,典型的例子就是垃圾回收線程,JVM內部使用這個線程來做并行的垃圾回收處理。

因為大多數的線程分配都是由Java EE容器完成的,所以能夠理解和認識線程堆棧跟蹤,并能從線程堆棧數據中識別出它來,對你而言很重要. 這可以讓你能夠快速的知道Java EE容器正要執行的是什么類型的請求.

從一個線程轉儲堆棧的分析角度來看,你將能了解從JVM發現的線程池之間的不同,并識別出請求的類型.

最后一節會向你提供對于HotSop VM而言什么是JVM線程堆棧的一個概述,還有你將會遇到的各種不同的線程. 而對 IBM VM 線程堆棧形式詳細內容將會在第四節向你提供.

請注意你可以從根本原因分析論壇獲得針對本文的線程堆棧示例.

JVM 線程堆棧——它是什么?

JVM線程堆棧是一個給定時間的快照,它能向你提供所有被創建出來的Java線程的完整清單.

每一個被發現的Java線程都會給你如下信息:

– 線程的名稱;經常被中間件廠商用來識別線程的標識,一般還會帶上被分配的線程池名稱以及狀態 (運行,阻塞等等.)

– 線程類型 & 優先級,例如 : daemon prio=3 ** 中間件程序一般以后臺守護的形式創建他們的線程,這意味著這些線程是在后臺運行的;它們會向它們的用戶提供服務,例如:向你的Java EE應用程序 **

– Java線程ID,例如 : tid=0x000000011e52a800 ** 這是通過 java.lang.Thread.getId() 獲得的Java線程ID,它常常用自增長的長整形 1..n** 實現

– 原生線程ID,例如 : nid=0x251c** ,之所以關鍵是因為原生線程ID可以讓你獲得諸如從操作系統的角度來看那個線程在你的JVM中使用了大部分的CPU時間等這樣的相關信息. **

– Java線程狀態和詳細信息,例如: waiting for monitor entry [0xfffffffea5afb000] java.lang.Thread.State: BLOCKED (on object monitor)

** 可以快速的了解到線程狀態極其當前阻塞的可能原因 **

– Java線程棧跟蹤;這是目前為止你能從線程堆棧中找到的最重要的數據. 這也是你花費最多分析時間的地方,因為Java棧跟蹤向提供了你將會在稍后的練習環節了解到的導致諸多類型的問題的根本原因,所需要的90%的信息。

– 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上的線程堆棧信息和線程池做了詳細的拆解,如下圖所示:

c71019125222a50b1a6c4fe490475612.png

上圖中可以看出線程堆棧是由多個不同部分組成的。這些信息對問題分析都很重要,但對不同的問題模式的分析會使用不同的部分(問題模式會在后面的文章中做模擬和演示。)

現在通過這個分析樣例,給大家詳細解釋一下HoteSpot上線程堆棧信息中的各個組成部分:

# Full thread dump標示符

“Full thread dump”是一個全局唯一的關鍵字,你可以在中間件和單機版本Java的線程堆棧信息的輸出日志中找到它(比如說在UNIX下使用:kill -3 )。這是線程堆棧快照的開始部分。

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,0xfffffffee040000

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534477.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534477.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534477.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 文件下載方法_【工具類】Java后臺上傳下載文件的幾種方式

/*** 將本地照片上傳至騰訊云服務上*/public void uploadImage(String localImagePath) throws Exception {// 1.將訂單照片上傳至騰訊地圖眾包側提供的云服務上try {File imageFile new File(localImagePath);if (imageFile.exists()) {String url "http://" map…

java io流讀取txt文件_Java使用IO流讀取TXT文件

通過BufferedReader讀取TXT文件window系統默認的編碼是GBK&#xff0c;而IDE的編碼多數為UTF-8&#xff0c;如果沒有規定new InputStreamReader(new FileInputStream(file),“GBK”)為GBK會出現讀取內容亂碼。//文件路徑String filePath"C:/Users/Admin/Desktop/products.…

c 調用java程序_C ++可以調用Java代碼嗎?

小編典典是的&#xff0c;您當然可以。這是一個例子&#xff1a;這是java文件&#xff1a;public class InvocationHelloWorld {public static void main(String[] args) {System.out.println("Hello, World!");System.out.println("Arguments sent to this pro…

java 大數類_Java大數類介紹

java能處理大數的類有兩個高精度大整數BigInteger和高精度浮點數BigDecimal&#xff0c;這兩個類位于java.math包內&#xff0c;要使用它們必須在類前面引用該包&#xff1a;importjava.math.BigInteger;和importjava.math.BigDecimal;或者importjava.math.*;以下從幾個方面對B…

java 畫樹_java – 如何繪制代表連接節點圖的樹?

我想在Java GUI中顯示樹,但我不知道如何.樹代表連接節點的圖形,如下所示&#xff1a;我應該說我有自己的樹類&#xff1a;public class BinaryTree{private BinaryNode root;public BinaryTree( ){root null;}public BinaryTree( Object rootItem ){root new BinaryNode( roo…

mysql 優化代碼_MySQL Order by 語句優化代碼詳解

Order by語句是用來排序的&#xff0c;經常我們會使用到Order by來進行排序&#xff0c;下面我給大家來講講Order by用法與優化排序&#xff0c;有需要的同學可參考MySQL Order By keyword是用來給記錄中的數據進行分類的。MySQL Order By Keyword根據關鍵詞分類ORDER BY keywo…

java.lang.class_關于Java.lang.Class的一些疑問

User.class可以在編譯時就確定下來Class的泛型&#xff0c;而new User().getClass()實際上是運行時才能確定下來實際是什么泛型。舉個例子&#xff1a;public class User{}public class Student extends User{public static void main(String[] args) {User user1 new User();…

java文件 linux_Linux執行Java文件

最近學習shell腳本&#xff0c;寫個簡單java類讓linux去執行java類沒別的東西&#xff0c;就引了一個fastjson的jar&#xff0c;寫了個main方法 序列化一個User對象 打印package com.lws.demo;import java.util.Date;import com.alibaba.fastjson.JSONObject;import com.lws.mo…

java 劊子手游戲_java基礎(九):容器

集合的引入List (ArrayList LinkedList)Set (HashSet LinkedHashSet TreeSet )Map (HashMap LinkedHashMap TreeMap)CollectionsIterator使用泛型1.為什么使用集合而不是數組&#xff1f;集合和數組相似點都可以存儲多個對象&#xff0c;對外作為一個整體存在數組的缺點長度必須…

java面試手寫單鏈表_(轉)面試大總結之一:Java搞定面試中的鏈表題目

packageLinkedListSummary;importjava.util.HashMap;importjava.util.Stack;/*** http://blog.csdn.net/luckyxiaoqiang/article/details/7393134 輕松搞定面試中的鏈表題目* http://www.cnblogs.com/jax/archive/2009/12/11/1621504.html 算法大全(1)單鏈表** 目錄&#xff1a…

ccf認證俄羅斯方塊java_CCF認證歷年試題 - osc_h3robkrt的個人空間 - OSCHINA - 中文開源技術交流社區...

CCF認證歷年試題不加索引整理會死星人orz第一題&#xff1a;CCF201712-1 最小差值(100分)CCF201703-1 分蛋糕(100分)CCF201612-1 中間數(100分)CCF201609-1 最大波動(100分)CCF201604-1 折點計數(100分)CCF201509-1 數列分段(100分)CCF201503-1 圖像旋轉(100分)CCF201412-1 門禁…

mysql 變量作表名查詢_使用MySQL函數變量作為表名查詢

我需要有一個表中增加一定的ID(如AUTO_INCREMENT)函數使用MySQL函數變量作為表名查詢我有水木清華這樣DELIMITER $$DROP FUNCTION IF EXISTS GetNextID$$CREATE FUNCTION GetNextID(tblName TEXT, increment INT)RETURNS INTDETERMINISTICBEGINDECLARE NextID INT;SELECT MAX(c…

java 簽名 ecdsa_Java實現ECDSA簽名算法

ECDSA簽名算法package com.albedo.security;/*** DSA 加解密實現*/public class ECDSAUtils extends Base {//字符編碼public static final String ALGORITHM "EC";public static final String SIGN_ALGORITHM "SHA1withECDSA";/*** ECDSA 驗簽** param …

java異常處理方式推薦做法_談談Java異常處理這件事兒

此文已由作者謝蕾授權網易云社區發布。歡迎訪問網易云社區&#xff0c;了解更多網易技術產品運營經驗。前言我們對于“異常處理”這個詞并不陌生&#xff0c;眾多框架和庫在異常處理方面都提供了便利&#xff0c;但是對于何種處理才是最佳實踐&#xff0c;也是眾說紛紜。異常處…

as400和java的區別_文件傳輸協議和AS400

我目前收到以下錯誤&#xff1a;遠程服務器返回錯誤&#xff1a;(501)參數或參數中的語法錯誤 .我已經檢查了服務器并且文件確實存在&#xff0c;如果我打開命令提示符并鍵入以下代碼它可以工作&#xff1a;ftpopen 192.168.1.2cd /Imagesget S12345.jpeg這是正常的&#xff0c…

java中同時兩人提交數據_如何一起發送JSON請求和發布表單數據請求?

所以這是一個應該在POST請求中接受以下參數的API&#xff1a;token (as form data)apiKey (as form data){"notification": {"id": 1,"heading": "some heading","subheading": "some subheading","image&qu…

java 64內存不足_請教一個 Java 內存占用的問題

第 1 條附言 364 天前2020-03-04 01:08:55.525 [HikariPool-1 housekeeper] WARN c.z.hikari.pool.HikariPool - HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta1m5s643ms48?s450ns).2020-03-04 01:09:08.516 [task-11] ERROR o.s.s.s.TaskU…

java 抽象類 final_final/抽象類/interface

lesson Thirteen                          2018-05-10 02:10:43final:最終的&#xff0c;可以修飾類、屬性、方法1.final修飾類&#xff1a;這個類就不能被繼承&#xff0c;如&#xff1a;String類&#xff0c;StringBuffer類&#xff0c;System類1…

java char i=2+#039;2#039;;_P039 二維數組的字符按列存放到字符串中 ★★

所屬年份&#xff1a;2010.9;2011.9;2012.3請編寫函數fun,該函數的功能是&#xff1a;將M行N列的二維數組中的字符數據,按列的順序依次放到一個字符串中。例如,若二維數組中的數據為W W W WS S S SH H H H則字符串中的內容應是&#xff1a;WSHWSHWSHWSH。#include#define M 3#d…

java io中斷_JDK源碼閱讀:InterruptibleChannel 與可中斷 IO

來源&#xff1a;木杉的博客 &#xff0c;imushan.com/2018/08/01/java/language/JDK源碼閱讀-InterruptibleChannel與可中斷IO/Java傳統IO是不支持中斷的&#xff0c;所以如果代碼在read/write等操作阻塞的話&#xff0c;是無法被中斷的。這就無法和Thead的interrupt模型配合使…