如何分析线程转储–线程堆栈跟踪
為了使您能夠從線程轉(zhuǎn)儲(chǔ)中快速識(shí)別問題模式,首先需要了解如何讀取線程堆棧跟蹤以及如何正確獲取“故事”。 這意味著,如果我要您告訴我#38線程在做什么? 您應(yīng)該能夠準(zhǔn)確回答; 包括“線程堆棧跟蹤”是否顯示正常(正常)與掛起狀態(tài)。
再談Java堆棧跟蹤
你們中的大多數(shù)人都熟悉Java堆棧跟蹤。 當(dāng)拋出Java異常時(shí),這是我們從服務(wù)器和應(yīng)用程序日志文件中找到的典型數(shù)據(jù)。 在這種情況下,Java堆棧跟蹤為我們提供了觸發(fā)Java異常的Thread的代碼執(zhí)行路徑,例如java.lang.NoClassDefFoundError,java.lang.NullPpointerException等。此類代碼執(zhí)行路徑使我們可以查看不同的層最終導(dǎo)致Java異常的代碼。
必須始終從下至上讀取Java堆棧跟蹤:
- 底部的行將顯示請求的始發(fā)者,例如Java / Java EE容器Thread。
- 堆棧跟蹤頂部的第一行將向您顯示觸發(fā)了最后一個(gè)Exception的Java類。
讓我們通過一個(gè)簡單的示例來完成此過程。 我們創(chuàng)建了一個(gè)示例Java程序,只需執(zhí)行一些Class方法調(diào)用并拋出Exception。 生成的程序輸出如下:
JavaStrackTraceSimulator Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.comException in thread "main" java.lang.IllegalArgumentException:at org.ph.javaee.training.td.Class2.call(Class2.java:12)at org.ph.javaee.training.td.Class1.call(Class1.java:14)at org.ph.javaee.training.td.JavaSTSimulator.main(JavaSTSimulator.java:20)- 調(diào)用Java程序JavaSTSimulator(通過“主”線程)
- 然后,模擬器從Class1調(diào)用方法call()
- 然后,Class1方法call()調(diào)用Class2方法call()
- Class2方法call()引發(fā)Java異常:java.lang.IllegalArgumentException
- 然后,在日志/標(biāo)準(zhǔn)輸出中顯示Java異常
如您所見,導(dǎo)致此異常的代碼執(zhí)行路徑始終從下至上顯示。
上面的分析過程對于任何Java程序員都應(yīng)該是眾所周知的。 接下來,您將看到線程轉(zhuǎn)儲(chǔ)線程堆棧跟蹤分析過程與上述Java堆棧跟蹤分析非常相似。
線程轉(zhuǎn)儲(chǔ):線程堆棧跟蹤分析
從JVM生成的線程轉(zhuǎn)儲(chǔ)為您提供了整個(gè)JVM進(jìn)程中所有“創(chuàng)建的”線程的代碼級執(zhí)行快照。 創(chuàng)建線程并不意味著所有這些線程實(shí)際上都在做某事。 在從Java EE容器JVM生成的典型線程轉(zhuǎn)儲(chǔ)快照中:
- 一些線程可能正在執(zhí)行原始計(jì)算任務(wù),例如XML解析,IO /磁盤訪問等。
- 一些線程可能正在等待一些阻塞的IO調(diào)用,例如遠(yuǎn)程Web服務(wù)調(diào)用,DB / JDBC查詢等。
- 那時(shí)某些線程可能涉及垃圾回收,例如GC線程
- 一些線程將等待一些工作要做(不做任何工作的線程通常進(jìn)入wait()狀態(tài))
- 一些線程可能正在等待其他一些線程完成工作,例如,一些線程正在等待獲取某些對象上的監(jiān)視器鎖定(同步塊{})
在下一篇文章中,我將返回上面的更多圖表,但現(xiàn)在讓我們集中討論堆棧跟蹤分析過程。 您的下一個(gè)任務(wù)是能夠盡您所能讀取線程堆棧跟蹤并了解它在做什么。
線程堆棧跟蹤為您提供了其當(dāng)前執(zhí)行的快照。 第一行通常包含線程的本機(jī)信息,例如其名稱,狀態(tài),地址等。當(dāng)前執(zhí)行堆棧跟蹤必須自下而上讀取。 請遵循以下分析過程。 您從線程轉(zhuǎn)儲(chǔ)分析中獲得的經(jīng)驗(yàn)越多,您就能越快地讀取并快速識(shí)別每個(gè)線程執(zhí)行的工作:
- 從底部開始讀取線程堆棧跟蹤
- 首先,確定發(fā)起者(Java EE容器線程,自定義線程,GC線程,JVM內(nèi)部線程,獨(dú)立的Java程序“主”線程等)。
- 下一步是確定線程正在執(zhí)行的請求的類型(WebApp,Web Service,JMS,遠(yuǎn)程EJB(RMI),內(nèi)部Java EE容器等)。
- 下一步是從執(zhí)行堆棧中識(shí)別出您所涉及的應(yīng)用程序模塊的形式,例如,線程正在嘗試執(zhí)行的實(shí)際核心工作。 分析的復(fù)雜性將取決于中間件環(huán)境和應(yīng)用程序的抽象層
- 下一步是查看第一行之前的最后?10-20行。 標(biāo)識(shí)線程所涉及的協(xié)議或工作,例如HTTP調(diào)用,套接字通信,JDBC或原始計(jì)算任務(wù),例如磁盤訪問,類加載等。
- 下一步是看第一行。 第一行通常告訴LOT處于Thread狀態(tài),因?yàn)樗悄臄z快照時(shí)執(zhí)行的當(dāng)前代碼
- 最后兩個(gè)步驟的組合將為您提供信息的核心,以總結(jié)線程所涉及的工作和/或懸掛條件
現(xiàn)在,使用從JBoss 5生產(chǎn)環(huán)境捕獲的Thread Dump Thread堆棧跟蹤的真實(shí)示例,在下面直觀地查看上述步驟。 在此示例中,許多線程在創(chuàng)建新的JAX-WS Service實(shí)例時(shí)都顯示了類似的問題,即IO過多。
如您所見,最后10行和第一行將告訴我們線程所涉及的掛起或緩慢狀態(tài)(如果有)。 底部的幾行將為我們提供發(fā)起者和請求類型的詳細(xì)信息。
我希望本文能幫助您了解正確的線程堆棧跟蹤分析的重要性。 當(dāng)我們在以后的文章中介紹最常見的線程轉(zhuǎn)儲(chǔ)問題模式時(shí),我將帶回更多的線程堆棧跟蹤示例。 現(xiàn)在,下一篇文章將教您如何在邏輯孤島中分解線程轉(zhuǎn)儲(chǔ)線程,并提出潛在的根本原因“可疑”列表。
參考: 如何分析線程轉(zhuǎn)儲(chǔ)–第5部分:來自JCG合作伙伴 Pierre-Hugues Charbonneau的Java EE支持模式和Java教程博客中的線程堆棧跟蹤 。
翻譯自: https://www.javacodegeeks.com/2012/07/how-to-analyze-thread-dump-thread-stack.html
總結(jié)
以上是生活随笔為你收集整理的如何分析线程转储–线程堆栈跟踪的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 长城守卫军有谁 谁是长城守卫军
- 下一篇: 与Maven 3,Failsafe和Ca