Search code examples
jvmdevopssystem-administration

Extracting JVM stack trace from a heap dump (hprof) with a command line tool


I want to automate the extraction of the stack trace from the JVM crash heap dump file on a headless server. Is there a non-GUI solution for this?


Solution

  • MAT project comes with a script ParseHeapDump.sh (*.bat on Windows), if you just run it on a heap dump like this: /path/to/MAT/ParseHeapDump.sh <HEAPDUMP_NAME>.hprof, you get a set of files, one of them being a text file <HEAPDUMP_NAME>.threads containing stack traces, e.g.:

    Thread 0x715883630
    
      locals:
    
    Thread 0x71577b418
      at java.lang.Object.wait(J)V (Native Method)
      at java.lang.ref.ReferenceQueue.remove(J)Ljava/lang/ref/Reference; (ReferenceQueue.java:155)
      at jdk.internal.ref.CleanerImpl.run()V (CleanerImpl.java:148)
      at java.lang.Thread.run()V (Thread.java:834)
      at jdk.internal.misc.InnocuousThread.run()V (InnocuousThread.java:134)
    
      locals:
        objectId=0x715833c30, line=1
        objectId=0x716df1990, line=1
        objectId=0x715832230, line=2
        objectId=0x71577b418, line=2
        objectId=0x71577b418, line=2
        objectId=0x71577b418, line=3
        objectId=0x71577b418, line=4
    
    Thread 0x715883050
      at jdk.internal.misc.Unsafe.park(ZJ)V (Native Method)
      at java.util.concurrent.locks.LockSupport.parkNanos(Ljava/lang/Object;J)V (LockSupport.java:234)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(J)J (AbstractQueuedSynchronizer.java:2123)
      at java.util.concurrent.DelayQueue.take()Ljava/util/concurrent/Delayed; (DelayQueue.java:229)
      at com.intellij.util.concurrency.AppDelayQueue.lambda$new$0()V (AppDelayQueue.java:26)
      at com.intellij.util.concurrency.AppDelayQueue$$Lambda$16.run()V (Unknown Source)
      at java.lang.Thread.run()V (Thread.java:834)
    
      locals:
        objectId=0x715883050, line=1
        objectId=0x715cd8a90, line=2
        objectId=0x7291c6618, line=2
        objectId=0x715f73520, line=3
        objectId=0x715cd8aa8, line=3
        objectId=0x715883050, line=3
        objectId=0x715f73520, line=4
        objectId=0x715cd8ac0, line=5
        objectId=0x715883050, line=6
    ...
    

    You are only interested in lines starting with Thread 0x... and at ... here.

    Notes:

    1. The script does a lot more work than would be necessary to only extract a thread dump (it parses the heap as well which is 99.99...% of work); and it generates many files that you do not need (all prefixed <HEAPDUMP_NAME>).
    2. Thread names are lost, and thread ids seem to not correspond to anything OS-specific (e.g. native thread id); in other words, you cannot find Thread 0x715883050 in the ps or top/htop output — at least I do not know a way.