- First run the process that needs to be debugged
- Run jps to get PIDs of running java processes. On Windows
jpsdid not give me all the PIDs. But this command worked [1]:wmic process where "name='java.exe'" get ProcessID, CommandLine - Once you have found the PID of process you need to debug, you can get heap statistics by running
jmap -histo:live <PID>
Read http://stackoverflow.com/a/35963059/147530 to understand the nuances esp. if you are getting this error:
Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding
Real world example:
Needed to debug a service that would cause an OOM exception after running for a while. Wrote following script to periodically make requests to the service (running at localhost:5622) every 10s and print out top 5 entries from `jmap`’s output:
#!/bin/bash
while true; do
#http://unix.stackexchange.com/questions/196549/hide-curl-output
curl -s localhost:5622 > /dev/null
jmap -histo:live $1 | head -n 8
sleep 10s
done
Save the script as `debug.sh`. Now can run the process and this script to get realtime output of memory usage:
$. debug.sh 76100
where 76100 is the PID of the java service obtained by running `jps`
See http://stackoverflow.com/questions/1087177/what-do-those-strange-class-names-in-a-java-heap-dump-mean to understand jmap’s output. Sample jmap output (truncated to top 5 entries):
num #instances #bytes class name
----------------------------------------------
1: 171821 14836520 [C
2: 6296 7004424 [B
3: 40 5243520 [Lcom.sun.tools.javac.util.SharedNameTable$NameImpl;
4: 133194 4262208 com.sun.tools.javac.util.SharedNameTable$NameImpl
5: 170551 4093224 java.lang.String
Troubleshooting:
Well-known file is not secure:
first thing to check is if the process you are debugging is owned by the same user which is used to start jmap.
if that is the case, the next thing to check is if /tmp/hsperfdata_$USER/$PID file is accessible to that user. Check permissions on both the file and the directory.
More details at:
http://blog.tsunanet.net/2010/10/ioexception-well-known-file-is-not.html
Jmap source code:
Using Eclipse MAT
Eclipse MAT is by far considered the most comprehensive tool for debugging heap dumps. One tip in case it fails to run on a Mac. Edit /Applications/MemoryAnalyzer.app/Contents/Eclipse/MemoryAnalyzer.ini and add following lines to it replacing paths as necessary:
-vm
/Library/Java/jdk-21.0.1.jdk/Contents/Home/bin
IMPORTANT: there needs to be a line break between -vm and /Library/Java/jdk-21.0.1.jdk/Contents/Home/bin. My complete file looks like following:
-vm
/Library/Java/jdk-21.0.1.jdk/Contents/Home/bin
-startup
../Eclipse/plugins/org.eclipse.equinox.launcher_1.6.600.v20231106-1826.jar
--launcher.library
../Eclipse/plugins/org.eclipse.equinox.launcher.cocoa.macosx.aarch64_1.2.800.v20231003-1442
-vmargs
--add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
-Xmx1024m
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XstartOnFirstThread
Another tip: change the -Xmx setting if you get OOM while opening a heap dump in Eclipse MAT.
Other Useful Commands to debug OOM
check system logs for OOM exceptions
sudo dmesg -T | grep -i 'oom'