• 深入JVM系列之(3):JavaCore和HeapDump


    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)Oracle JVM
    如果使用Oracle JVM也就是标准的SUN JVM(SUN已被oracle收购)当内存溢出时生成heapdump文件配置如下
    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
    与生成heapdump相关的命令行参数:
    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:UsersIBM_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:

    输出的各列的含义。可见该命令也主要针对运行时内存。

    ColumnDescription
    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:UsersIBM_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

  • 相关阅读:
    C++ linux 共享内存的学习
    C++11 result_of 学习
    C++线程池 基于Cpp98的实现 学习2 未完待续
    Piecewise Smooth Subdivision Surfaces with Normal Control 未完待续
    C++线程池 基于C的实现 学习1
    C++ 标准函数 。abort & typeid
    线段树(区间更新, 区间查询 ,线段染色)
    bfs(标记整个棋盘)
    stringstream流分割空格
    lcm与gcd
  • 原文地址:https://www.cnblogs.com/hzg1981/p/5558065.html
Copyright © 2020-2023  润新知