jvm 生成javacore和heapdump文件
在Server端開發與運維中,經常需要生成javacore和heapdump文件,以便分析jvm的運行狀態。javacore文件中給出jvm線程的詳細情況,而heapdump文件則給出jvm的運行時內存的使用情況,對分析JVM的內存泄漏有重要的作用。其中,javacore文件一般是文本文件,而heapdump則一般是二進制文件,需要使用專門的分析工具進行分析,一般常用的工具為IBM的heap anylizer。JavaCore是關於CPU的,而HeapDump文件是關於內存的。
JavaCore文件主要保存的是Java應用各線程在某一時刻的運行的位置,即JVM執行到哪一個類、哪一個方法、哪一個行上。它是一個文本文件,打開后可以看到每一個線程的執行棧,以stack trace的顯示。通過對JavaCore文件的分析可以得到應用是否“卡”在某一點上,即在某一點運行的時間太長,例如數據庫查詢,長期得不到響應,最終導致系統崩潰等情況。
一般JavaCore文件生成兩個比較有效,可以對比這兩個JavaCore文件,來對比哪個線程“卡”住了。
HeapDump文件是一個二進制文件,它保存了某一時刻JVM堆中對象使用情況,這種文件需要相應的工具進行分析,如IBM Heap Analyzer這類工具。這類文件最重要的作用就是分析系統中是否存在內存溢出的情況。
1 -Xloggc:${目錄}/temp_gc.log (GC日志文件) 2 -XX:+HeapDumpOnOutOfMemoryError (內存溢出時生成heapdump文件) 3 -XX:HeapDumpPath=${目錄} (heapdump文件存放位置)
如果要即時動態生成heapdump文件可以使用jmap命令, jdk6.0已取消了-XX:+HeapDumpOnCtrlBreak配置參數通過ctrl+break的方式。
1 jmap -dump:format=b,file=temp_heapdump.hprof
而javacore文件的生成,則需要依賴於kill命令,當jvm進程被殺死的時候,生成javacore文件。
(2)HP JVM
1 -Xverbosegc:file=${目錄}/temp_gc.log (GC日志文件) 2 -XX:+HeapDumpOnOutOfMemoryError (內存溢出時生成heapdump文件) 3 -XX:+HeapDumpOnCtrlBreak (可以通過ctrl+break組合鍵動態生成heapdump文件 HP JVM也在jdk6中取消了這一方式嗎??) 4 -XX:HeapDumpPath=${目錄} (heapdump文件存放位置)
(3)IBM JVM
非windows操作系統環境中
1 -XverboseGClog: ${目錄}/temp_gc.log (GC日志文件) 2 -Xdump:heap:events=user,file=${目錄}/pid%uid%pid.phd
表示可以根據需要通過kill -3 產生DUMP文件,%uid和%pid為變量
windows操作系統環境中:啟動wsadmin,進入wsadmin環境
1 wsadmin> set jvm [$AdminControl completeObjectName type=JVM,process=server1,*] 2 wsadmin> $AdminControl invoke $jvm generateHeapDump 3 wsadmin> $AdminControl invoke $jvm dumpThreads
以上主要是通過命令行,配置使用kill命令生成javacore和heapdump文件。
on-the-fly way
linux環境下,使用ps -ef 或者ps -aux命令,或者top命令,得到pid,然后使用kill 命令殺死特定進程,產生java core 和heap dump 文件。kill命令就是用戶向進程發送signal。
那么問題來了: kill命令必須殺死進程才能獲得java core和heap dump文件,能否在不殺死進程的情況下產生這兩個文件呢?
實際上,jdk給我們提供了多種工具命令,這些命令保存在jdk的bin目錄下,它們被稱為Standard JDK Tools and Utilities。基本的工具有:appletviewer, apt, extcheck, jar, java, javac, javadoc, 等等。 而用來Troubleshooting的工具主要有:jinfo, jhat, jmap, jsadebugd, jstack,jstat等等。
jmap:
jmap prints shared object memory maps or heap memory details of a given process or core file or a remote debug server. If the given process is running on a 64-bit VM, you may need to specify the -J-d64 option, e.g.:
jmap -J-d64 -heap pid
jmap輸出如下:
1 C:\Users\IBM_ADMIN>jmap -J-d64 -heap 9952 2 Attaching to process ID 9952, please wait... 3 Debugger attached successfully. 4 Server compiler detected. 5 JVM version is 25.60-b23 6 7 using thread-local object allocation. 8 Parallel GC with 4 thread(s) 9 10 Heap Configuration: 11 MinHeapFreeRatio = 0 12 MaxHeapFreeRatio = 100 13 MaxHeapSize = 1073741824 (1024.0MB) 14 NewSize = 89128960 (85.0MB) 15 MaxNewSize = 357564416 (341.0MB) 16 OldSize = 179306496 (171.0MB) 17 NewRatio = 2 18 SurvivorRatio = 8 19 MetaspaceSize = 21807104 (20.796875MB) 20 CompressedClassSpaceSize = 1073741824 (1024.0MB) 21 MaxMetaspaceSize = 17592186044415 MB 22 G1HeapRegionSize = 0 (0.0MB) 23 24 Heap Usage: 25 PS Young Generation 26 Eden Space: 27 capacity = 348651520 (332.5MB) 28 used = 4341152 (4.140045166015625MB) 29 free = 344310368 (328.3599548339844MB) 30 1.245126365718985% used 31 From Space: 32 capacity = 1048576 (1.0MB) 33 used = 0 (0.0MB) 34 free = 1048576 (1.0MB) 35 0.0% used 36 To Space: 37 capacity = 1048576 (1.0MB) 38 used = 0 (0.0MB) 39 free = 1048576 (1.0MB) 40 0.0% used 41 PS Old Generation 42 capacity = 525860864 (501.5MB) 43 used = 280628384 (267.6280822753906MB) 44 free = 245232480 (233.87191772460938MB) 45 53.36551989539195% used 46 47 36434 interned Strings occupying 3405440 bytes.
jhat:
parses a java heap dump file and launches a webserver. jhat enables you to browse heap dumps using your favorite webbrowser.
jstat:
輸出的各列的含義。可見該命令也主要針對運行時內存。
Column | Description |
---|---|
S0 | Survivor space 0 utilization as a percentage of the space's current capacity. |
S1 | Survivor space 1 utilization as a percentage of the space's current capacity. |
E | Eden space utilization as a percentage of the space's current capacity. |
O | Old space utilization as a percentage of the space's current capacity. |
P | Permanent space utilization as a percentage of the space's current capacity. |
YGC | Number of young generation GC events. |
YGCT | Young generation garbage collection time. |
FGC | Number of full GC events. |
FGCT | Full garbage collection time. |
GCT | Total garbage collection time. |
jstack:
jstack prints Java stack traces of Java threads for a given Java process or core file or a remote debug server.
jstack -J-d64 -m pid
- -m
- prints mixed mode (both Java and native C/C++ frames) stack trace.
樣例輸出如下:
1 C:\Users\IBM_ADMIN>jstack -J-d64 -m 9952 2 Attaching to process ID 9952, please wait... 3 Debugger attached successfully. 4 Server compiler detected. 5 JVM version is 25.60-b23 6 Deadlock Detection: 7 8 No deadlocks found. 9 10 ----------------- 0 ----------------- 11 0x00000000776e937a USER32!WaitMessage + 0xa 12 ----------------- 1 ----------------- 13 ----------------- 2 ----------------- 14 ----------------- 3 ----------------- 15 ----------------- 4 ----------------- 16 ----------------- 5 ----------------- 17 ----------------- 6 ----------------- 18 ----------------- 7 ----------------- 19 ----------------- 8 ----------------- 20 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 21 ----------------- 9 ----------------- 22 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 23 ----------------- 10 ----------------- 24 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 25 ----------------- 11 ----------------- 26 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 27 ----------------- 12 ----------------- 28 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 29 ----------------- 13 ----------------- 30 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 31 ----------------- 14 ----------------- 32 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 33 ----------------- 15 ----------------- 34 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 35 ----------------- 16 ----------------- 36 ----------------- 17 ----------------- 37 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 38 ----------------- 18 ----------------- 39 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 40 ----------------- 19 ----------------- 41 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 42 ----------------- 20 ----------------- 43 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 44 ----------------- 21 ----------------- 45 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 46 ----------------- 22 ----------------- 47 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 48 ----------------- 23 ----------------- 49 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 50 ----------------- 24 ----------------- 51 0x000000007793c0ea ntdll!NtWaitForMultipleObjects + 0xa 52 ----------------- 25 ----------------- 53 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 54 ----------------- 26 ----------------- 55 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 56 ----------------- 27 ----------------- 57 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 58 ----------------- 28 ----------------- 59 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 60 ----------------- 29 ----------------- 61 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 62 ----------------- 30 ----------------- 63 0x000000007793c0ea ntdll!NtWaitForMultipleObjects + 0xa 64 ----------------- 31 ----------------- 65 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 66 ----------------- 32 ----------------- 67 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 68 ----------------- 33 ----------------- 69 ----------------- 34 ----------------- 70 ----------------- 35 ----------------- 71 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 72 ----------------- 36 ----------------- 73 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 74 ----------------- 37 ----------------- 75 ----------------- 38 ----------------- 76 0x000000007793c0ea ntdll!NtWaitForMultipleObjects + 0xa 77 ----------------- 39 ----------------- 78 0x000000007793c0ea ntdll!NtWaitForMultipleObjects + 0xa 79 ----------------- 40 ----------------- 80 0x000000007793c0ea ntdll!NtWaitForMultipleObjects + 0xa 81 ----------------- 41 ----------------- 82 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 83 ----------------- 42 ----------------- 84 ----------------- 43 ----------------- 85 0x000000007793c0ea ntdll!NtWaitForMultipleObjects + 0xa 86 ----------------- 44 ----------------- 87 ----------------- 45 ----------------- 88 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 89 ----------------- 46 ----------------- 90 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 91 ----------------- 47 ----------------- 92 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 93 ----------------- 48 ----------------- 94 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 95 ----------------- 49 ----------------- 96 ----------------- 50 ----------------- 97 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 98 ----------------- 51 ----------------- 99 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa 100 ----------------- 52 ----------------- 101 0x000000007793bb7a ntdll!ZwWaitForSingleObject + 0xa
基本看不懂。。。
結論: 要想debug一個真正的bug,還得靠詳細的javacore文件和heapdump文件!
參考文獻:
http://www.codeceo.com/article/java-javacore-heapdump.html
http://blog.itpub.net/14710393/viewspace-754416
工具集:
http://docs.oracle.com/javase/7/docs/technotes/tools/index.html#jconsole
http://docs.oracle.com/javase/7/docs/technotes/tools/share/jmap.html
http://docs.oracle.com/javase/7/docs/technotes/tools/share/jhat.html
http://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html
http://docs.oracle.com/javase/7/docs/technotes/tools/share/jstack.html