![]() |
|
級(jí)別: 初級(jí)
隋 鵬飛 (suipf@cn.ibm.com), 軟件工程師, IBM
伍 亦方 (wuyifang@cn.ibm.com), 軟件工程師, IBM
2009 年 3 月 11 日
本文將向讀者介紹利用 Java dump 診斷 JVM Crash 和 CPU 饑餓等問(wèn)題的方法和技巧,以便使用戶更加全面的了解 Java dump 在故障診斷過(guò)程中的作用。
![]() |
|
對(duì)于大型 java 應(yīng)用程序來(lái)說(shuō),再精細(xì)的測(cè)試都難以堵住所有的漏洞,即便我們?cè)跍y(cè)試階段進(jìn)行了大量卓有成效的工作,很多問(wèn)題還是會(huì)在生產(chǎn)環(huán)境下暴露出來(lái),并且很難在測(cè)試環(huán)境中進(jìn)行重現(xiàn)。JVM 能夠記錄下問(wèn)題發(fā)生時(shí)系統(tǒng)的運(yùn)行狀態(tài)并將其存儲(chǔ)在轉(zhuǎn)儲(chǔ)(dump)文件中,從而為我們分析和診斷問(wèn)題提供了重要的依據(jù)。常見(jiàn)的轉(zhuǎn)儲(chǔ)文件包括 Java Dump, Heap dump 和 System dump。這里我們主要介紹 Java dump 在 JVM 故障診斷中的應(yīng)用。
Java dump,也叫做 Thread dump,是 JVM 故障診斷中最重要的轉(zhuǎn)儲(chǔ)文件之一。JVM 的許多問(wèn)題都可以使用這個(gè)文件進(jìn)行診斷,其中比較典型的包括線程阻塞,CPU 使用率過(guò)高,JVM Crash,堆內(nèi)存不足,和類裝載等問(wèn)題。作為一款輕量級(jí)(與 Heap dump 和 System dump 相比)的轉(zhuǎn)儲(chǔ)文件,Java dump 的確是我們?cè)\斷 JVM 問(wèn)題的首選。本文將系統(tǒng)的介紹使用 Java dump 進(jìn)行 JVM 故障診斷的方法和技巧,希望能夠?yàn)榇蠹姨峁┮恍椭?/p>
![]() ![]() |
![]()
|
Java dump 通常是文本格式(.txt),因此可以通過(guò)一般的文本編輯器進(jìn)行閱讀,閱讀時(shí)需要注意段與行的格式:
為了便于大家的分析,Java dump 的每一段的開(kāi)頭,都會(huì)用“-----”與上一段明顯的區(qū)分開(kāi)來(lái)。而每一段的標(biāo)題也會(huì)用“=====”作為標(biāo)識(shí),這樣我們就能夠很容易的找到每一段的開(kāi)頭和標(biāo)題部分(如清單 1)。
清單 1. Java dump 段標(biāo)題示例
NULL -------------------------------- 0SECTION TITLE subcomponent dump routine NULL =============================== |
Java dump 文件中,每一行都包含一個(gè)標(biāo)簽,這個(gè)標(biāo)簽最多由 15 個(gè)字符組成(如清單2中所示)。其中第一位數(shù)字代表信息的詳細(xì)級(jí)別(0,1,2,3,4),級(jí)別越高代表信息越詳細(xì);接下來(lái)的兩個(gè)字符是段標(biāo)題的縮寫(xiě),比如,“CI” 代表 “Command-line interpreter”,“CL” 代表 “Class loader”,“LK” 代表 “Locking”,“ST” 代表 “Storage”,“TI” 代表 “Title”,“XE” 代表 “Execution engine”等等;其余部分為信息的概述。
清單 2. Java dump 行標(biāo)簽和內(nèi)容示例
1TISIGINFO Dump Event "uncaught" (00008000) Detail "java/lang/OutOfMemoryError" received |
不同版本的 JVM 所產(chǎn)生的 Java dump 的格式可能會(huì)稍有不同,但基本上都會(huì)包含以下幾個(gè)方面的內(nèi)容:
- TITLE 信息塊:描述 JAVA DUMP 產(chǎn)生的原因,時(shí)間以及文件的路徑。
- GPINFO信息塊:GPF 信息。
- ENVINFO 信息塊:系統(tǒng)運(yùn)行時(shí)的環(huán)境及 JVM 啟動(dòng)參數(shù)。
- MEMINFO 信息塊:內(nèi)存的使用情況和垃圾回收記錄。
- LOCKS 信息塊:用戶監(jiān)視器(Monitor)和系統(tǒng)監(jiān)視器(Monitor)。
- THREADS信息塊:所有 java 線程的狀態(tài)信息和執(zhí)行堆棧。
- CLASSES信息塊:類加載信息。
![]() ![]() |
![]()
|
由于 Java dump 文件包含的內(nèi)容比較廣泛,因此 JVM 的很多問(wèn)題都可以通過(guò) java dump進(jìn)行診斷。這些問(wèn)題主要包括線程阻塞,CPU 使用率過(guò)高,JVM Crash,堆內(nèi)存不足,和類裝載等問(wèn)題。
線程阻塞是我們?cè)?java 多線程編程中經(jīng)常遇到的問(wèn)題。由于對(duì)后端有限資源的爭(zhēng)用以及過(guò)度同步等問(wèn)題,經(jīng)常會(huì)發(fā)現(xiàn) Java dump 中某個(gè)資源(鎖對(duì)象)下有太多的線程處于等待狀態(tài),這時(shí)候我們通常需要從以下三個(gè)方面去診斷這個(gè)問(wèn)題:
- 這個(gè)鎖存在的目的是什么?有沒(méi)有可能去掉這個(gè)鎖或者縮小這個(gè)鎖保護(hù)的范圍,從而減少線程等待問(wèn)題發(fā)生的幾率。
- 有哪些線程需要用到這個(gè)鎖,有沒(méi)有可能改用其它更好的替代方案。
- 當(dāng)前哪個(gè)線程正在持有這個(gè)鎖,持有的時(shí)間是多長(zhǎng),有沒(méi)有可能縮短持有的時(shí)間。
比線程阻塞更嚴(yán)重的是死鎖問(wèn)題,當(dāng)兩個(gè)以上的線程互相等待對(duì)方的鎖,從而形成一個(gè)環(huán)的時(shí)候,就會(huì)發(fā)生死鎖。關(guān)于如何使用 Java dump 診斷死鎖的問(wèn)題,請(qǐng)參考 在 WebSphere Application Server V6.1 應(yīng)用程序中跟蹤死鎖 一文,該文對(duì)此問(wèn)題做了較為詳細(xì)的介紹。
JVM Crash 是我們所碰到的最棘手的問(wèn)題之一,它對(duì)整個(gè)系統(tǒng)的影響是致命的,并且總是讓人防不勝防。導(dǎo)致 JVM 崩潰的原因有很多,通常都是一些底層的錯(cuò)誤。比如 JVM 本身的 bug,錯(cuò)誤的 JNI 調(diào)用,第三方原生模塊(比如數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序)中的 bug 等。JVM崩潰的原因復(fù)雜,并且大多都難以重現(xiàn),所以診斷起來(lái)有一定的難度。
一般來(lái)說(shuō),JVM 崩潰的時(shí)候,系統(tǒng)一般會(huì)自動(dòng)產(chǎn)生一個(gè) Java dump 文件(JVM 默認(rèn)的設(shè)置參數(shù)就會(huì)觸發(fā))。這個(gè) Java dump 會(huì)幫我們記錄下 JVM 崩潰的原因,相關(guān)的信息會(huì)記錄在 TITLE 信息塊,GPINFO 信息塊和 THREADS 信息塊中。
- TITLE 信息塊:用于確認(rèn)問(wèn)題產(chǎn)生的原因,即是否是由于一些底層錯(cuò)誤而導(dǎo)致 JVM Crash。
- GPINFO 信息塊:用于查看問(wèn)題的詳細(xì)信息和問(wèn)題定位。
- THREADS信息塊:用于了解問(wèn)題線程的運(yùn)行情況。
下面我們通過(guò)一個(gè)具體的例子來(lái)介紹 JVM Crash 問(wèn)題的診斷方法。TestJni 是一個(gè)簡(jiǎn)單的 Java 應(yīng)用,它通過(guò) JNI 調(diào)用本地代碼 CallJin.dll 中的 doSomeThing() 函數(shù)。
清單 3. 在 TestJni 類中調(diào)用 CallJin.dll 中的函數(shù)
package test; public class TestJin { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub TestJin testObj = new TestJin(); testObj.work(); } public void work() { CallJni.doSomeThing(); } } package test; public class CallJni { static { System.loadLibrary("CallJni"); System.out.println("Dll Loaded"); } public native static void doSomeThing(); } |
CallJin.dll 是 C++ 編寫(xiě)得本地庫(kù),其源代碼如清單 3 所示:
清單 4. CallJni.dll 的 C++ 實(shí)現(xiàn)代碼
#include <com_test_CallJni.h> /* * Class: com_test_CallJni * Method: doSomeThing */ JNIEXPORT void JNICALL Java_test_CallJni_doSomeThing (JNIEnv *, jclass){ int *i; *i = 100; } |
在這段 C++ 代碼中,整形指針 I 還沒(méi)有分配空間就被賦了值,這是一個(gè)非常嚴(yán)重的錯(cuò)誤。當(dāng)然 java 應(yīng)用程序員并不知道這一點(diǎn),并且在 java 應(yīng)用程序中調(diào)用了 doSomeThing() 這個(gè) JNI 函數(shù)。結(jié)果導(dǎo)致 JVM 發(fā)生了崩潰。
在這段 C++ 代碼中,整形指針 I 還沒(méi)有分配空間就被賦了值,這是一個(gè)非常嚴(yán)重的錯(cuò)誤。當(dāng)然 java 應(yīng)用程序員并不知道這一點(diǎn),并且在 java 應(yīng)用程序中調(diào)用了 doSomeThing() 這個(gè) JNI 函數(shù)。結(jié)果導(dǎo)致 JVM 發(fā)生了崩潰。
下面是 JVM 崩潰時(shí),系統(tǒng)為我們生成的 Java dump 文件的片斷。
清單5. Java dump 文件片斷
NULL ---------------------------------------------- 0SECTION TITLE subcomponent dump routine NULL =============================== 1TISIGINFO Dump Event "gpf" (00002000) received 1TIDATETIME Date: 2008/11/12 at 20:45:24 1TIFILENAME Javacore filename: C:\eclipse\workspace\Serviceability\TestApps\SampleLeak\TestJin\ javacore.20081112.204522.5656.txt |
從 TITLE 信息塊中我們可以看到,這個(gè) java 是由一個(gè) "gpf" 事件觸發(fā)的,GPF 是 General Protection Fault 的縮寫(xiě),表明應(yīng)用程序發(fā)生了一般性保護(hù)錯(cuò)誤,這種錯(cuò)誤常常導(dǎo)致 JVM 突然崩潰。
除了 "gpf" 之外,Java dump 還可能由如下事件觸發(fā)(清單 6)。
清單 6. 常見(jiàn) Java dump 觸發(fā)事件
user SIGQUIT signal (Ctrl-Brk on Windows, Ctrl-\ on Linux, Ctrl-V on z/OS) abort a controlled crash, as triggered by the abort() system call vmstart the VM has finished initialization vmstop the VM is about to shutdown load a new class has been loaded unload a classloader has been unloaded throw a Java exception has been thrown catch a Java exception has been caught uncaught a Java exception was not handled by the application thrstart a new thread has started thrstop an old thread has stopped blocked a thread is blocked entering a monitor fullgc garbage collection has started |
從 TITLE 信息塊,我們只能初步了解問(wèn)題產(chǎn)生的原因,如果要進(jìn)一步了解問(wèn)題的詳細(xì)信息,還要查看 GPINFO 信息塊(清單 7):
清單7. GPINFO 信息塊
NULL ---------------------------------------------- 0SECTION GPINFO subcomponent dump routine NULL ================================ 2XHOSLEVEL OS Level : Windows XP 5.1 build 2600 Service Pack 3 2XHCPUS Processors - 3XHCPUARCH Architecture : x86 3XHNUMCPUS How Many : 2 NULL 1XHEXCPCODE J9Generic_Signal_Number: 00000004 1XHEXCPCODE ExceptionCode: C0000005 1XHEXCPCODE ExceptionAddress: 412E136E 1XHEXCPCODE ContextFlags: 0001003F 1XHEXCPCODE Handler1: 7EFB04E0 1XHEXCPCODE Handler2: 7F057A80 1XHEXCPCODE InaccessibleAddress: CCCCCCCC NULL 1XHEXCPMODULE Module: C:\eclipse\workspace\Serviceability\TestApps\SampleLeak\TestJin\CallJni.dll 1XHEXCPMODULE Module_base_address: 412D0000 1XHEXCPMODULE Offset_in_DLL: 0001136E NULL 1XHFLAGS VM flags:00040000 NULL |
GPINFO 信息塊中我們可以找到問(wèn)題的異常代碼,ExceptionCode: C0000005
代表內(nèi)存訪問(wèn)錯(cuò)誤或者非法的內(nèi)存操作。Module: C:\eclipse\workspace\Serviceability\TestApps\TestJin\CallJni.dll
指明了發(fā)生問(wèn)題的原生模塊。 CallJni.dll 這個(gè)動(dòng)態(tài)連接庫(kù)是我們自己的 JNI 代碼,因此很容易發(fā)現(xiàn)問(wèn)題的所在。在一個(gè)復(fù)雜的 java 運(yùn)行環(huán)境下,很多時(shí)候異常是在第三方的代碼庫(kù)中產(chǎn)生的,我們沒(méi)有辦法查看源代碼中的問(wèn)題,這時(shí)候只能通過(guò)文件名中的一些關(guān)鍵字來(lái)推測(cè)問(wèn)題發(fā)生的位置,這些關(guān)鍵字包括(清單 8):
清單 8. 需要注意的關(guān)鍵字
GC = garbage collection/collector (how Java frees memory) JIT = just-in-time compiler, a feature of JVM JDBC = Java feature for database access ORB = object request broker, lower layer of app server JMS = java messaging service, feature of web server or add-on |
例如,Module: C:\JDK\IBM\java1.5.0\jre\bin\j9jit23.dll
說(shuō)明 JIT 模塊發(fā)生問(wèn)題,用戶可以使用 JITC_COMPILEOPT 變量的 SKIP 選項(xiàng)禁用對(duì)當(dāng)前方法進(jìn)行 JIT 編譯,然后再對(duì)系統(tǒng)的運(yùn)行情況進(jìn)行進(jìn)一步的跟蹤。
JITC_COMPILEOPT=SKIP{failingPackage/failingClass}{failingMethod}
除此之外,查看 THREADS 信息塊中當(dāng)前線程的執(zhí)行堆棧也有助于我們對(duì)問(wèn)題的診斷。從清單 9 我們可以看到 main 線程在執(zhí)行 CallJni.doSomeThing 方法數(shù)的過(guò)程中發(fā)生了問(wèn)題,據(jù)此我們可以返回源代碼中查找相應(yīng)的方法,進(jìn)而確定問(wèn)題的根源。
清單 9. Threads 信息塊
NULL ---------------------------------------------------- 0SECTION THREADS subcomponent dump routine NULL ================================= NULL 1XMCURTHDINFO Current Thread Details NULL ---------------------- 3XMTHREADINFO "main" (TID:0x408C7C00, sys_thread_t:0x00366278, state:R, native ID:0x000016CC) prio=5 4XESTACKTRACE at test/CallJni.doSomeThing(Native Method) 4XESTACKTRACE at test/TestJin.work(TestJin.java:16) 4XESTACKTRACE at test/TestJin.main(TestJin.java:11) NULL |
CPU 使用率過(guò)高可能是由于某些線程陷入了死循環(huán)或者執(zhí)行了不適當(dāng)?shù)牟僮饕鸬模湓\斷方法就是將這些線程找出來(lái),修正問(wèn)題或者進(jìn)行代碼優(yōu)化。由于 Java Dump 中并沒(méi)有包含各線程的資源使用情況,因此我們需要結(jié)合其他的操作系統(tǒng)命令/工具(prstat、top、pslist 等等),將 CPU 使用率較高的線程映射到 Java Dump 中,并分析這些線程的狀態(tài)以及可能發(fā)生的問(wèn)題。
從下面這段 PSList 的輸出結(jié)果中我們可以看到 jvm 內(nèi)部每個(gè)線程消耗的總的“用戶時(shí)間”和“內(nèi)核時(shí)間”,比較幾次 PSList 的輸出結(jié)果,我們就能從中找出那些 CPU 使用時(shí)間顯著增加的線程,再將這些線程的 TID 映射到Java Dump中,進(jìn)而查看問(wèn)題線程的詳細(xì)信息。
清單 10. PSList 的輸出結(jié)果
pslist -d <Java PID> Tid Pri Cswtch State User Time Kernel Time Elapsed Time 2908 8 2025 Wait:Executive 0:00:00.359 0:00:01.312 1:48:08.046 4344 15 157 Wait:UserReq 0:00:00.218 0:00:00.015 1:48:07.921 4836 15 415456 Wait:UserReq 0:00:00.000 0:00:00.000 1:48:07.921 2496 8 1 Wait:UserReq 0:00:00.000 0:00:00.000 1:48:07.796 4648 9 1 Wait:UserReq 0:00:00.000 0:00:00.000 1:48:07.796 3116 9 7 Wait:UserReq 0:00:00.000 0:00:00.000 1:48:07.796 5268 8 189 Wait:UserReq 0:00:00.015 0:00:00.000 1:48:07.796 5220 7 6991523 Running 1:47:42.031 0:00:01.218 1:48:05.593 3932 9 2 Wait:UserReq 0:00:00.000 0:00:00.000 1:48:05.125 |
與線程死鎖問(wèn)題不同,在分析 CPU 利用率過(guò)高的問(wèn)題時(shí),我們不需要關(guān)心那些處于等待狀態(tài)的線程,因?yàn)榫€程處于等待狀態(tài)不需要消耗 CPU 資源。我們關(guān)注的重點(diǎn)應(yīng)該是 THREADS 信息塊中那些正在運(yùn)行(state:R 狀態(tài))的線程。很多時(shí)候?yàn)榱朔治鼍€程狀態(tài)的一些變化,我們需要對(duì)比多個(gè) Java Dump 文件,看哪些線程狀態(tài)發(fā)生了變化,哪些一直在執(zhí)行相同的函數(shù),從而找出那些可疑的問(wèn)題線程。
除了 Thread 相關(guān)的信息外,Java Dump 還包含 Memory 和 GC 等方面的信息,雖然這些信息不像 Heap Dump 和 VerboseGC 那么詳細(xì),但對(duì)于一些比較簡(jiǎn)單的問(wèn)題定位還是很有幫助的。例如,下面的 Java dump 清單中,Dump Event "uncaught" (00008000) Detail "java/lang/OutOfMemoryError" received
告訴我們問(wèn)題是由于內(nèi)存溢出引起的,并且從 MEMINFO 信息塊中可以找到當(dāng)前堆中的空間使用情況, 1ffa0 的剩余空間說(shuō)明系統(tǒng)的可用堆內(nèi)存已經(jīng)嚴(yán)重不足了,需要我們擴(kuò)大堆內(nèi)存的大小或者修改應(yīng)用程序使其占用更少的內(nèi)存。
清單 11. MEMINFO 信息塊
NULL ---------------------------------------------------- 0SECTION TITLE subcomponent dump routine NULL =============================== 1TISIGINFO Dump Event "uncaught" (00008000) Detail "java/lang/OutOfMemoryError" received 1TIDATETIME Date: 2008/04/20 at 19:13:50 1TIFILENAME Javacore filename: c:\Serviceability\AppServer\profiles\AppSrv01\javacore.20080420.185326.948.txt NULL ---------------------------------------------------- 0SECTION MEMINFO subcomponent dump routine NULL ================================= 1STHEAPFREE Bytes of Heap Space Free: 1ffa0 1STHEAPALLOC Bytes of Heap Space Allocated: 40000000 |
常見(jiàn)的類加載問(wèn)題包括: ClassNotFoundException,Jar 包沖突以及由類裝入引發(fā)的其他問(wèn)題(例如 jdk 1.4 中的內(nèi)存碎片問(wèn)題) Java Dump 文件的 Classes 信息塊的格式如清單中示,這些信息可以幫我們確定以下問(wèn)題:
- 當(dāng)前系統(tǒng)中有哪些 Class 文件被加載進(jìn)來(lái)。
- 確認(rèn)某個(gè) Class 是否被正確的 ClassLoader 所加載,即不同的 ClassLoader 之間是否有 Jar 包沖突。
- 已經(jīng)加載的 Class 的個(gè)數(shù)。在IBM Jre1.4中,我們可以參考系統(tǒng)中 Class 的個(gè)數(shù)來(lái)設(shè)置 KCluster 的大小。
清單 12. CLASSES 信息塊
NULL --------------------------------------------------------- 0SECTION CLASSES subcomponent dump routine NULL ================================= 1CLTEXTCLLOS Classloader summaries 1CLTEXTCLLSS 12345678: 1=primordial,2=extension,3=shareable,4=middleware,5=system, 6=trusted,7=application,8=delegating 2CLTEXTCLLOADER p---st-- Loader *System*(0x008DA0B0) 3CLNMBRLOADEDLIB Number of loaded libraries 3 3CLNMBRLOADEDCL Number of loaded classes 347 2CLTEXTCLLOADER -x--st-- Loader sun/misc/Launcher$ExtClassLoader(0x008E5E38), Parent *none*(0x00000000) 3CLNMBRLOADEDLIB Number of loaded libraries 0 3CLNMBRLOADEDCL Number of loaded classes 0 2CLTEXTCLLOADER -----ta- Loader sun/misc/Launcher$AppClassLoader(0x008EF3E0), Parentsun/misc/Launcher$ExtClassLoader(0x008E5E38) 3CLNMBRLOADEDLIB Number of loaded libraries 0 3CLNMBRLOADEDCL Number of loaded classes 2 1CLTEXTCLLIB ClassLoader loaded libraries 2CLTEXTCLLIB Loader *System*(0x008DA0B0) 3CLTEXTLIB C:\JDK\IBM\java1.5.0\jre\bin\java 3CLTEXTLIB C:\JDK\IBM\java1.5.0\jre\bin\jclscar_23 3CLTEXTLIB C:\JDK\IBM\java1.5.0\jre\bin\zip 1CLTEXTCLLOD ClassLoader loaded classes 2CLTEXTCLLOAD Loader *System*(0x008DA0B0) 3CLTEXTCLASS java/io/ByteArrayOutputStream(0x40D40098) 3CLTEXTCLASS sun/nio/ByteBuffered(0x40D40330) 3CLTEXTCLASS java/lang/ref/PhantomReference(0x40DB9360) 3CLTEXTCLASS sun/misc/Cleaner(0x40DB94A8) |
![]() ![]() |
![]()
|
關(guān)于 Java dump,下面是一些有可能讓你產(chǎn)生困惑的問(wèn)題:
為什么發(fā)生 JVM Crash 時(shí),JVM 沒(méi)有自動(dòng)生成 Java dump 文件?
答:這種情況大多與系統(tǒng)的環(huán)境變量或者 JVM 啟動(dòng)參數(shù)的設(shè)置有關(guān),比如設(shè)置了 DISABLE_JAVADUMP=true,IBM_NOSIGHANDLER=true
等等,因此可以首先檢查系統(tǒng)設(shè)置和 JVM 啟動(dòng)參數(shù)。當(dāng)然也不排除因?yàn)橐恍┎淮_定因素導(dǎo)致 JVM 無(wú)法產(chǎn)生 Java dump,雖然這種可能性比較小。
JVM 在生成 Java dump 的同時(shí)也生成了 Heap dump,它們之間有沒(méi)有什么聯(lián)系?
答:有,但是關(guān)系不大。因?yàn)?java dump 主要反映的是線程的運(yùn)行狀態(tài),而 Heap dump 則主要反映對(duì)象之間的引用關(guān)系,所以兩者之間沒(méi)有太大的聯(lián)系。有時(shí)候我們可以通過(guò)鎖對(duì)象或者 Class 對(duì)象的起始地址找到它在 Heap dump 中的位置,但大多數(shù)時(shí)候這對(duì)故障診斷并沒(méi)有多大意義。
為什么有些 java dump 的鎖沒(méi)有 owner?
答:并不是所有的鎖都被其它線程持有,有些鎖是用作主動(dòng)等待的,比如 sleep() ,wait(),join() 等,這些鎖并沒(méi)有被其它線程占用,被它阻塞的線程只是在等待通知,即 “Waiting to be notified”。從線程狀態(tài)上看,這些鎖一般都處于 “CW” 狀態(tài)。
Java Dump 中的很多線程處于 state:CW 和 state:B 狀態(tài),它們之間有何區(qū)別?
答:兩者都處于等待狀態(tài)。不同是:
CW - Condition Wait – 條件等待. 這種等待一般是線程主動(dòng)等待或者正在進(jìn)行某種 IO 操作,而并非等待其它線程釋放資源。比如 sleep() ,wait(),join() 等方法的調(diào)用。
B – Blocked – 線程被阻塞,與條件等待不同,線程被阻塞一般不是線程主動(dòng)進(jìn)行的,而是由于當(dāng)前線程需要的資源正在被其他線程占用,因此不得不等待資源釋放以后才能繼續(xù)執(zhí)行,例如 synchronized 代碼塊。
為什么我在 PsList 里看到的線程無(wú)法映射到 Java dump 中?
答:由于很多操作系統(tǒng)工具和命令輸出的線程的 TID 都是十進(jìn)制的,映射到 Java dump 時(shí)首先要將其轉(zhuǎn)換為十六進(jìn)制數(shù)字,然后再到 Java dump 中查找對(duì)應(yīng)的 native ID。Java dump 中每個(gè)線程都有兩個(gè)ID, 一個(gè)是 java 線程的TID, 另一個(gè)是對(duì)應(yīng)操作系統(tǒng)線程的 native ID。
閱讀 Websphere Appliaction Server 產(chǎn)生的 Java dump 文件有沒(méi)有什么特別的技巧?
答:對(duì)于 WAS 應(yīng)用程序來(lái)說(shuō),線程信息往往要比一般的應(yīng)用程序復(fù)雜的多。記住一些常見(jiàn)的 ThreadName 可以幫助我們更好的理解應(yīng)用程序的運(yùn)行狀態(tài),例如:
線程名 | 線程信息 |
Web Container: # | WAS web container * |
Alarm Thread # | handles timer processing |
Session.Transports.Threads:### | servlet threads for processing HTTP requests |
ORB.thread.pool:### | ORB thread (ORB data) |
P=437206:O=0: StandardRT=19027:LocalPort=9001:RemoteHost=hostname.ibm.com:RemoteP |
an ORB thread for receiving an EJB request or other ORB request |
Thread-## | JVM thread (default name) |
![]() ![]() |
![]()
|
本文比較全面的介紹了 Java dump 在 JVM 故障診斷過(guò)程中的作用。正像你所看到的,Java dump 文件主要幫我們解決與線程相關(guān)的各種問(wèn)題,但同時(shí)它還為我們提供了很多其它有用的信息(比如 JVM Crash),在某些情況下,這些信息對(duì)于我們至關(guān)重要,所以充分的利用 Java dump 文件可以幫我們更快的找到解決問(wèn)題的方向。
學(xué)習(xí)
- 在 WebSphere Application Server V6.1 應(yīng)用程序中跟蹤死鎖:介紹了利用Java Dump跟蹤死鎖問(wèn)題的步驟和方法。
- 類裝入問(wèn)題解密,第 1 部分: 類裝入和調(diào)試工具介紹:討論類裝入問(wèn)題的系列文章之一。
- IBM JDK1.5 Information Center:幫您了解 IBM JVM 的工作機(jī)制、診斷技術(shù)、診斷工具等。
- WebSphere Application Server V7 專題:為您總結(jié)了與 WAS V7 相關(guān)最新的內(nèi)容和資源,其中包括入門(mén)介紹及開(kāi)發(fā)技巧、配置與管理、遷移、監(jiān)控與測(cè)試等。
- WebSphere 產(chǎn)品家族新特性系列 :本專題向您提供了目前 WebSphere 系列中新產(chǎn)品的新增功能的介紹。
- WebSphere Application Server 常見(jiàn)問(wèn)題及解答:向您提供了關(guān)于 IBM WebSphere Application Server 產(chǎn)品家族的問(wèn)題集錦。
- WebSphere Application Server 產(chǎn)品專題:在這里您可以獲得關(guān)于 WebSphere Application Server 最新的文章、教程等技術(shù)資源。
獲得產(chǎn)品和技術(shù)