103

I have a HotSpot JVM heap dump that I would like to analyze. The VM ran with -Xmx31g, and the heap dump file is 48 GB large.

  • I won't even try jhat, as it requires about five times the heap memory (that would be 240 GB in my case) and is awfully slow.
  • Eclipse MAT crashes with an ArrayIndexOutOfBoundsException after analyzing the heap dump for several hours.

What other tools are available for that task? A suite of command line tools would be best, consisting of one program that transforms the heap dump into efficient data structures for analysis, combined with several other tools that work on the pre-structured data.

4
  • Are you sure the dump is not corrupt and that you are using a more recent version of the DTFJ JARs? The ArrayIndexOutOfBoundsException features in atleast two bugs. I'm stating this because you haven't reported an OOME when running MAT, which has a different fix. Commented Aug 31, 2011 at 7:59
  • jhat uses heapMap to store the objects read, which grows exponentially with the number of objects stored in heap. One option is to change the decl's from heapMap to TreeMap, and run the heap size of jhat as least as large as your process.
    – codeDr
    Commented May 13, 2013 at 14:44
  • 1
    I have drafted a proposal for a memory mapped backend for Eclipse MAT that would allow you to process much larger files than your local available heap, so long as you have sufficient local disk to spill to. Feedback welcome bugs.eclipse.org/bugs/show_bug.cgi?id=572512
    – jasonk
    Commented May 6, 2021 at 1:54
  • @codeDr I doubt that it grows exponentially. Maybe quadratic, and that would be bad enough already. Commented May 6, 2021 at 10:19

12 Answers 12

105

Normally, what I use is ParseHeapDump.sh included within Eclipse Memory Analyzer and described here, and I do that onto one our more beefed up servers (download and copy over the linux .zip distro, unzip there). The shell script needs less resources than parsing the heap from the GUI, plus you can run it on your beefy server with more resources (you can allocate more resources by adding something like -vmargs -Xmx40g -XX:-UseGCOverheadLimit to the end of the last line of the script. For instance, the last line of that file might look like this after modification

./MemoryAnalyzer -consolelog -application org.eclipse.mat.api.parse "$@" -vmargs -Xmx40g -XX:-UseGCOverheadLimit

Run it like ./path/to/ParseHeapDump.sh ../today_heap_dump/jvm.hprof

After that succeeds, it creates a number of "index" files next to the .hprof file.

After creating the indices, I try to generate reports from that and scp those reports to my local machines and try to see if I can find the culprit just by that (not just the reports, not the indices). Here's a tutorial on creating the reports.

Example report:

./ParseHeapDump.sh ../today_heap_dump/jvm.hprof org.eclipse.mat.api:suspects

Other report options:

org.eclipse.mat.api:overview and org.eclipse.mat.api:top_components

If those reports are not enough and if I need some more digging (i.e. let's say via oql), I scp the indices as well as hprof file to my local machine, and then open the heap dump (with the indices in the same directory as the heap dump) with my Eclipse MAT GUI. From there, it does not need too much memory to run.

EDIT: I just liked to add two notes :

  • As far as I know, only the generation of the indices is the memory intensive part of Eclipse MAT. After you have the indices, most of your processing from Eclipse MAT would not need that much memory.
  • Doing this on a shell script means I can do it on a headless server (and I normally do it on a headless server as well, because they're normally the most powerful ones). And if you have a server that can generate a heap dump of that size, chances are, you have another server out there that can process that much of a heap dump as well.
7
  • 5
    Important note: ParseHeapDump.sh is packaged with the Linux version only, not the OSX version -- eclipse.org/mat/downloads.php Commented Apr 1, 2013 at 18:30
  • When I try this (ssh'd to bash on a linux box), it fails immediately with "Unable to initialize GTK+". So it looks like (the current version, 2016-04-15) still thinks it's talking to a UI(?). Commented Apr 15, 2016 at 19:37
  • 2
    Hmm, the newer versions of ParseHeapDump.sh want to run ./MemoryAnalyzer directly. I am experimenting with running the launcher directly with java, so far that seems to be working, e.g. java -Xmx16g -Xms16g -jar plugins/org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar -consoleLog -consolelog -application org.eclipse.mat.api.parse "$@" Commented Apr 15, 2016 at 20:32
  • 1
    Appears you can use it on OS X by downloading both the Linux and OSX versions, then copy ParseHeapDump.sh to the same dir as your MemoryAnalyze file (in my case, ~/Downloads/mat.app/Contents/MacOS) and modify and run it there. Or run it on some remote server of course, via SSH :)
    – rogerdpack
    Commented Oct 24, 2016 at 20:01
  • Opened a 2GB heap dump with Eclipse Memory Analyzer GUI using no more than 500MB memory. Index files were created on the fly on file opening (taken ~30sec). Maybe they improved the tool. It is more convinient than copy big files back and forth, if it really works this way. Small memory footprint even without any console utilities is a big plus for me. But to be honest, I didn't try it with really big dumps (50+ GB). Very interesting how much memory is required to open and analyze such big dumps with this tool. Commented Aug 1, 2018 at 23:16
8

First step: increase the amount of RAM you are allocating to MAT. By default it's not very much and it can't open large files.

In case of using MAT on MAC (OSX) you'll have file MemoryAnalyzer.ini file in MemoryAnalyzer.app/Contents/MacOS. It wasn't working for me to make adjustments to that file and have them "take". You can instead create a modified startup command/shell script based on content of this file and run it from that directory. In my case I wanted 20 GB heap:

./MemoryAnalyzer -vmargs -Xmx20g --XX:-UseGCOverheadLimit ... other params desired

Just run this command/script from Contents/MacOS directory via terminal, to start the GUI with more RAM available.

2
  • Thanks. DLd the utility today. Tried run by 2x-click and it gave an error. Looked at log, could not create data file and said to use a switch. Opened the .app package and found MemoryAnalyzer.ini in the Eclipse\ folder, not \MacOS. Ah-ha! So I extracted all files locally and did as you suggested. I created a .sh file in \MacOS and moved the commands in Eclipse\MemoryAnalyzer.ini into it as a flat single line. Saved file. Ran the .sh file from MacOS\ on the command line and voila, it worked. Commented Jan 16, 2019 at 17:22
  • What a confusing mess. The MemoryAnalyzer.ini is not where it is supposed to be and even if you move it from Eclipse to MacOS the mods do not "take". All this to help nudge MAT to not run out of memory when it is trying to analyze a java heap which ran out of memory. My java hprof is 1.7GB and I am running on MacOS 10.15.7 Catalina. I do not believe the ini really takes, no matter where you put it on Mac. The Eclipse doc is wrong. Commented Jan 29, 2022 at 16:55
6

I suggest trying YourKit. It usually needs a little less memory than the heap dump size (it indexes it and uses that information to retrieve what you want)

6

The accepted answer to this related question should provide a good start for you (if you have access to the running process, generates live jmap histograms instead of heap dumps, it's very fast):

Method for finding memory leak in large Java heap dumps

Most other heap analysers (I use IBM http://www.alphaworks.ibm.com/tech/heapanalyzer) require at least a percentage of RAM more than the heap if you're expecting a nice GUI tool.

Other than that, many developers use alternative approaches, like live stack analysis to get an idea of what's going on.

Although I must question why your heaps are so large? The effect on allocation and garbage collection must be massive. I'd bet a large percentage of what's in your heap should actually be stored in a database / a persistent cache etc etc.

5

This person http://blog.ragozin.info/2015/02/programatic-heapdump-analysis.html

wrote a custom "heap analyzer" that just exposes a "query style" interface through the heap dump file, instead of actually loading the file into memory.

https://github.com/aragozin/heaplib

Though I don't know if "query language" is better than the eclipse OQL mentioned in the accepted answer here.

2
4

The latest snapshot build of Eclipse Memory Analyzer has a facility to randomly discard a certain percentage of objects to reduce memory consumption and allow the remaining objects to be analyzed. See Bug 563960 and the nightly snapshot build to test this facility before it is included in the next release of MAT. Update: it is now included in released version 1.11.0.

2
  • Any idea how to do that without the UI?
    – sam
    Commented Jan 13, 2022 at 9:25
  • 1
    See Batch mode with the following options: 1. -discard_ratio=percentage. Option to discard a fraction of the objects from huge dumps. 2. -discard_pattern=regex. A regular expression matching the class names of objects to be discarded. 3. -discard_offset=offset value. Controls which particular objects are discarded. 4. -discard_seed=random number generator seed. Controls which particular objects are discarded. Commented Jan 14, 2022 at 10:58
2

A not so well known tool - http://dr-brenschede.de/bheapsampler/ works well for large heaps. It works by sampling so it doesn't have to read the entire thing, though a bit finicky.

1
  • Unfortunately it says "common problem: running out of memory: Increase the -Xmx to 2/3 of the dump-size" but I suppose if you have enough RAM or can run it on a server with enough, that might be enough, thanks!
    – rogerdpack
    Commented Oct 25, 2016 at 18:17
2

This is not a command line solution, however I like the tools:

Copy the heap dump to a server large enough to host it. It is very well possible that the original server can be used.

Enter the server via ssh -X to run the graphical tool remotely and use jvisualvm from the Java binary directory to load the .hprof file of the heap dump.

The tool does not load the complete heap dump into memory at once, but loads parts when they are required. Of course, if you look around enough in the file the required memory will finally reach the size of the heap dump.

1

When the problem can be "easily" reproduced, one unmentioned alternative is to take heap dumps before memory grows that big (e.g., jmap -dump:format=b,file=heap.bin <pid>).

In many cases you will already get an idea of what's going on without waiting for an OOM.

In addition, MAT provides a feature to compare different snapshots, which can come handy (see https://stackoverflow.com/a/55926302/898154 for instructions and a description).

1

Idea is that use the headless MAT option , as in windows system with limited RAM you cannot do the analysis of large heap dump files.

  1. Download the latest mat for unix env - eg. MemoryAnalyzer-1.14.0.20230315-linux.gtk.x86_64.zip https://www.eclipse.org/mat/downloads.php , and extract in any directory of your server.

    Update the MAT config present in /MAT-folder-path/MemoryAnalyzer.ini :

    • MAT tool requires min jdk-17 , set JVM path ( version > java-17 )

    • Increase the heap memory eg -Xmx16384m as per heap dump size.

       -vm  
       /path-to/jdk-17/bin  
       -vmargs  
       -Xmx16384m 
      
  2. Useful to have a utility script for generating reports out of your heap dump file - heapAnalysis.sh (Do keep the free disc space > twice the heap dump size)

        #!/bin/sh
        heapFilePath="$1";
        if [[ -z $heapFilePath ]]; then
             echo "The heapFilePath received : $heapFilePath";
             if [ -f $heapFilePath ]; then
                 # MAT folder path : - ParseHeapDump.sh script
                 matDirectory="/MAT-folder-path/mat"
                 matScript="ParseHeapDump.sh"
    
                 heapDumpParserScript=$matDirectory/$matScript
    
                 # To parse the heap dump file and generate the html report in zip format.
                 echo "[1] Leak suspect report analysis started..";
                 $heapDumpParserScript $heapFilePath org.eclipse.mat.api:suspects
                 echo "Analysis completed : Leak suspect report.";
    
                 # You can comment out below [2] and [3] blocks. Usually LeakSuspect report helps in 80% of cases.
    
                 echo "[2] System overview report analysis started..";
                 $heapDumpParserScript $heapFilePath org.eclipse.mat.api:overview
                 echo "Analysis completed : System overview report.";
    
                 echo" [3] Top Component report analysis started..";
                 $heapDumpParserScript $heapFilePath org.eclipse.mat.api:top_components
                 echo "Analysis completed : Top Component report.";
            else
                 echo "Provide the correct filepath of heap dump, $heapFilePath file doesn't exist.";
            fi 
        else 
             echo "Provide the mandatory argument of the script."; 
         fi 
    
  3. To execute the script to analyze heap dump. ( Use screen utility to detach your session in unix terminal to avoid aborting the process. Because such analysis takes hours. )

          source /script/heapAnalysis.sh /path-to/heapDumpFile.hprof
    
  4. Now you can download the html report (~few mb size) into your local system using winSCP tool. If you want, you can transfer the indexed files (ParseHeapDump.sh creates indexed files ) into windows system and load using MAT

0

I came across an interesting tool called JXray. It provides limited evaluation trial license. Found it very useful to find memory leaks. You may give it a shot.

0

Try using jprofiler , its works good in analyzing large .hprof, I have tried with file sized around 22 GB.

https://www.ej-technologies.com/products/jprofiler/overview.html

$499/dev license but has a free 10 day evaluation

Not the answer you're looking for? Browse other questions tagged or ask your own question.