How to get a thread and heap dump of a Java process on Windows that's not running in a console

JavaJvmHeap DumpThread Dump

Java Problem Overview


I have a Java application that I run from a console which in turn executes an another Java process. I want to get a thread/heap dump of that child process.

On Unix, I could do a kill -3 <pid> but on Windows AFAIK the only way to get a thread dump is Ctrl-Break in the console. But that only gives me the dump of the parent process, not the child.

Is there another way to get that heap dump?

Java Solutions


Solution 1 - Java

You can use jmap to get a dump of any process running, assuming you know the pid.

Use Task Manager or Resource Monitor to get the pid. Then

jmap -dump:format=b,file=heap.hprof <pid>

to get the heap for that process.

For systems where bash and pgrep are installed and a single Java process is running, try:

jmap -dump:format=b,file=heap.hprof $(pgrep java)

Solution 2 - Java

You are confusing two different java dumps. kill -3 generates a thread dump, not a heap dump.

> Thread dump = stack traces for each thread in the JVM output to stdout as text. > >Heap dump = memory contents for the JVM process output to a binary file.

To take a thread dump on Windows, CTRL+BREAK if your JVM is the foreground process is the simplest way. If you have a unix-like shell on Windows like Cygwin or MobaXterm, you can use kill -3 {pid} like you can in Unix.

To take a thread dump in Unix, CTRL+C if your JVM is the foreground process or kill -3 {pid} will work as long as you get the right PID for the JVM.

With either platform, Java comes with several utilities that can help. For thread dumps, jstack {pid} is your best bet. http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstack.html

Just to finish the dump question out: Heap dumps are not commonly used because they are difficult to interpret. But, they have a lot of useful information in them if you know where/how to look at them. The most common usage is to locate memory leaks. It is a good practice to set the -D on the java command-line so that the heap dump is generated automatically upon an OutOfMemoryError, -XX:+HeapDumpOnOutOfMemoryError But, you can manually trigger a heap dump, also. The most common way is to use the java utility jmap.

NOTE: this utility is not available on all platforms. As of JDK 1.6, jmap is available on Windows.

An example command-line would look something like

jmap -dump:file=myheap.bin {pid of the JVM}

The output "myheap.bin" is not human readable (for most of us), and you will need a tool to analyze it. My preference is MAT. http://www.eclipse.org/mat/

Solution 3 - Java

I think the best way to create .hprof file in Linux process is with jmap command. For example: jmap -dump:format=b,file=filename.hprof {PID}

Solution 4 - Java

In addition to using the mentioned jconsole/visualvm, you can use jstack -l <vm-id> on another command line window, and capture that output.

The <vm-id> can be found using the task manager (it is the process id on windows and unix), or using jps.

Both jstack and jps are include in the Sun JDK version 6 and higher.

Solution 5 - Java

I recommend the Java VisualVM distributed with the JDK (jvisualvm.exe). It can connect dynamically and access the threads and heap. I have found in invaluable for some problems.

Solution 6 - Java

If you are on server-jre 8 and above you can use this:

jcmd PID GC.heap_dump /tmp/dump

Solution 7 - Java

Try one of below options.

  1. For 32 bit JVM:

     jmap -dump:format=b,file=<heap_dump_filename> <pid>
    
  2. For 64 bit JVM (explicitly quoting):

     jmap -J-d64 -dump:format=b,file=<heap_dump_filename> <pid>
    
  3. For 64 bit JVM with G1GC algorithm in VM parameters (Only live objects heap is generated with G1GC algorithm):

     jmap -J-d64 -dump:live,format=b,file=<heap_dump_filename> <pid>
    

Related SE question: https://stackoverflow.com/questions/36604102/java-heap-dump-error-with-jmap-command-premature-eof/

Have a look at various options of jmap at this article

Solution 8 - Java

If you want a heapdump on out-of-memory, you can start Java with the option -XX:-HeapDumpOnOutOfMemoryError

c.f. JVM Options reference page

Solution 9 - Java

You can send the kill -3 <pid> from Cygwin. You have to use the Cygwin ps options to find windows processes then just send the signal to that process.

Solution 10 - Java

You could run jconsole (included with Java 6's SDK) then connect to your Java application. It will show you every Thread running and its stack trace.

Solution 11 - Java

You have to redirect output from second java executable to some file. Then, use SendSignal to send "-3" to your second process.

Solution 12 - Java

The following script uses PsExec to connect to another Windows Session so it works even when connected via Remote Desktop Service.

I wrote a small batch script for Java 8 (using PsExec and jcmd) named jvmdump.bat, which dumps the threads, heap, system properties, and JVM args.

:: set the paths for your environment
set PsExec=C:\Apps\SysInternals\PsExec.exe
set JAVA_HOME=C:\Apps\Java\jdk1.8.0_121
set DUMP_DIR=C:\temp

@echo off

set PID=%1

if "%PID%"=="" (
	echo usage: jvmdump.bat {pid}
	exit /b
)

for /f "tokens=2,3,4 delims=/ " %%f in ('date /t') do set timestamp_d=%%h%%g%%f
for /f "tokens=1,2 delims=: " %%f in ('time /t') do set timestamp_t=%%f%%g
set timestamp=%timestamp_d%%timestamp_t%
echo datetime is: %timestamp%

echo ### Version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.version >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.uptime >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Command >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.command_line >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.flags >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

echo. >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
echo ### Properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"
%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% VM.system_properties >>"%DUMP_DIR%\%PID%-%timestamp%-jvm.log"

%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% Thread.print -l >"%DUMP_DIR%\%PID%-%timestamp%-threads.log"

%PsExec% -s %JAVA_HOME%\bin\jcmd.exe %PID% GC.heap_dump "%DUMP_DIR%\%PID%-%timestamp%-heap.hprof"

echo Dumped to %DUMP_DIR%

It must be run in the same Windows session of the user that started the JVM, so if you connect through Remote Desktop you might need to launch a command prompt in Session 0 and run it from there. e.g.

%PsExec% -s -h -d -i 0 cmd.exe

This will prompt you (click the taskbar icon at the bottom) to View the message in the interactive session, which will take you to the new console in the other session from which you can run the jvmdump.bat script.

Solution 13 - Java

How to get process id of java application?

Execute the command 'jcmd' to get the process id of java applications.

How to get Thread dump?

jcmd PID Thread.print > thread.dump

Reference link

You can even use jstack to get thread dump (jstack PID > thread.dump). Reference link

How to get heap dump?

Use jmap tool to get heap dump. jmap -F -dump:live,format=b,file=heap.bin PID

PID stands for process id of the application. Reference link

Solution 14 - Java

If you are using JDK 1.6 or above, You can use jmap command to take a heap Dump of a Java process, condition is you should known ProcessID.

If you are on Windows Machine, you can use Task Manager to get PID. For Linux machine you can use varieties of command like ps -A | grep java or netstat -tupln | grep java or top | grep java, depends on your application.

Then you can use the command like jmap -dump:format=b,file=sample_heap_dump.hprof 1234 where 1234 is PID.

There are varieties of tool available to interpret the hprof file. I will recommend Oracle's visualvm tool, which is simple to use.

Solution 15 - Java

If you can't (or don't want) to use the console/terminal for some reason, there is an alternative solution. You can make the Java application print the thread dump for you. The code that collects the Stack Trace is reasonable simple and can be attached to a button or a web interface.

private static String getThreadDump() {
	Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();

	StringBuilder out = new StringBuilder();
	for (Map.Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
		Thread thread = entry.getKey();
		StackTraceElement[] elements = entry.getValue();
		out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
		out.append('\n');

		for (StackTraceElement element : elements) {
			out.append(element.toString()).append('\n');
		}
		out.append('\n');
	}
	return out.toString();
}

This method will return a string that looks like this:

main | prio=5 | RUNNABLE
java.lang.Thread.dumpThreads(Native Method)
java.lang.Thread.getAllStackTraces(Thread.java:1607)
Main.getThreadDump(Main.java:8)
Main.main(Main.java:36)

Monitor Ctrl-Break | prio=5 | RUNNABLE
java.net.PlainSocketImpl.initProto(Native Method)
java.net.PlainSocketImpl.<clinit>(PlainSocketImpl.java:45)
java.net.Socket.setImpl(Socket.java:503)
java.net.Socket.<init>(Socket.java:424)
java.net.Socket.<init>(Socket.java:211)
com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:59)

Finalizer | prio=8 | WAITING
java.lang.Object.wait(Native Method)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

Reference Handler | prio=10 | WAITING
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:502)
java.lang.ref.Reference.tryHandlePending(Reference.java:191)
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

For those interested in a Java 8 version with streams, the code is even more compact:

private static String getThreadDump() {
	Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
	StringBuilder out = new StringBuilder();
	allStackTraces.forEach((thread, elements) -> {
		out.append(String.format("%s | prio=%d | %s", thread.getName(), thread.getPriority(), thread.getState()));
		out.append('\n');

		Arrays.stream(elements).forEach(element -> out.append(element.toString()).append('\n'));
		out.append('\n');
	});
	return out.toString();
}

You can easily test this code with:

System.out.print(getThreadDump());

Solution 16 - Java

Below java code is used to get the Heap Dump of a Java Process by providing a remote process' PID. The Program uses Remote JMX connection to dump heap to a file. It may be helpful for some one. Doesn't require jmap.

import java.lang.management.ManagementFactory;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.reflect.Method;

public class HeapDumper {

public static final String HOST = "192.168.11.177";
public static final String PORT = "1600";
public static final String FILE_NAME = "heapDump.hprof";
public static final String FOLDER_PATH = "C:/";
private static final String HOTSPOT_BEAN_NAME ="com.sun.management:type=HotSpotDiagnostic";

public static void main(String[] args) {
	if(args.length == 0) {
		System.out.println("Enter PID of the Java Process !!!");
		return;
	}
	
	String pidString = args[0];
	int pid = -1;
	if(pidString!=null && pidString.length() > 0) {
		try {
			pid = Integer.parseInt(pidString);
		}
		catch(Exception e) {
			System.out.println("PID is not Valid !!!");
			return;
		}
	}
	boolean isHeapDumpSuccess = false;
	boolean live = true;
	if(pid > 0) {
		MBeanServerConnection beanServerConn = getJMXConnection();
		
		if(beanServerConn!=null) {
			Class clazz = null;
			String dumpFile = FOLDER_PATH+"/"+FILE_NAME;
			try{
				clazz = Class.forName("com.sun.management.HotSpotDiagnosticMXBean");
				Object hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(beanServerConn, HOTSPOT_BEAN_NAME, clazz);
				Method method = clazz.getMethod("dumpHeap", new Class[]{String.class , boolean.class});
				method.setAccessible(true);
				method.invoke(hotspotMBean , new Object[] {dumpFile, new Boolean(live)});
				isHeapDumpSuccess = true;
			}
			catch(Exception e){
				e.printStackTrace();
				isHeapDumpSuccess = false;
			}
			finally{
				clazz = null;
			}
		}
	}
	
	if(isHeapDumpSuccess){
		System.out.println("HeapDump is Success !!!");
	}
	else{
		System.out.println("HeapDump is not Success !!!");
	}
}

private static MBeanServerConnection getJMXConnection() {
	MBeanServerConnection mbeanServerConnection = null;
	String urlString = "service:jmx:rmi:///jndi/rmi://" + HOST + ":" + PORT + "/jmxrmi";
	try {
		JMXServiceURL url = new JMXServiceURL(urlString);
        JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
        mbeanServerConnection = jmxConnector.getMBeanServerConnection();
        System.out.println("JMX Connection is Success for the URL :"+urlString);
	}
	catch(Exception e) {
		System.out.println("JMX Connection Failed !!!");
	}
	return mbeanServerConnection;
}

}

Solution 17 - Java

Maybe jcmd?

Jcmd utility is used to send diagnostic command requests to the JVM, where these requests are useful for controlling Java Flight Recordings, troubleshoot, and diagnose JVM and Java Applications.

The jcmd tool was introduced with Oracle's Java 7 and is particularly useful in troubleshooting issues with JVM applications by using it to identify Java processes' IDs (akin to jps), acquiring heap dumps (akin to jmap), acquiring thread dumps (akin to jstack), viewing virtual machine characteristics such as system properties and command-line flags (akin to jinfo), and acquiring garbage collection statistics (akin to jstat). The jcmd tool has been called "a swiss-army knife for investigating and resolving issues with your JVM application" and a "hidden gem."

Here’s the process you’ll need to use in invoking the jcmd:

  1. Go to jcmd <pid> GC.heap_dump <file-path>
  2. In which
  3. pid: is a Java Process Id, for which the heap dump will be captured Also, the
  4. file-path: is a file path in which the heap dump is be printed.

Check it out for more information about taking Java heap dump.

Solution 18 - Java

Inorder to take thread dump/heap dump from a child java process in windows, you need to identify the child process Id as first step.

By issuing the command: jps you will be able get all java process Ids that are running on your windows machine. From this list you need to select child process Id. Once you have child process Id, there are various options to capture thread dump and heap dumps.

Capturing Thread Dumps:

There are 8 options to capture thread dumps:

  1. jstack
  2. kill -3
  3. jvisualVM
  4. JMC
  5. Windows (Ctrl + Break)
  6. ThreadMXBean
  7. APM Tools
  8. jcmd

Details about each option can be found in this article. Once you have capture thread dumps, you can use tools like fastThread, Samuraito analyze thread dumps.

Capturing Heap Dumps:

There are 7 options to capture heap dumps:

  1. jmap

  2. -XX:+HeapDumpOnOutOfMemoryError

  3. jcmd

  4. JVisualVM

  5. JMX

  6. Programmatic Approach

  7. Administrative consoles

Details about each option can be found in this article. Once you have captured heap dump, you may use tools like Eclipse Memory Analysis tool, HeapHero to analyze the captured heap dumps.

Solution 19 - Java

Visualvm followup:

If you "can't connect" to your running JVM from jvisualvm because you didn't start it with the right JVM arguments (and it's on remote box), run jstatd on the remote box, then, assuming you have a direct connection, add it as a "remote host" in visualvm, double click the host name, and all other JVM's on that box will magically show up in visualvm.

If you don't have "direct connection" to ports on that box, you can also do this through a proxy.

Once you can see the process you want, drill into it in jvisualvm and use monitor tab -> "heapdump" button.

Solution 20 - Java

On a Oracle JDK, we have a command called jmap (available in the bin folder of Java Home). usage of the command comes as follows

> jmap (option) (pid)

Example: jmap -dump:live,format=b,file=heap.bin (pid)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmacgregView Question on Stackoverflow
Solution 1 - JavarkagandaView Answer on Stackoverflow
Solution 2 - JavaDerekView Answer on Stackoverflow
Solution 3 - JavaRoberto FloresView Answer on Stackoverflow
Solution 4 - JavaankonView Answer on Stackoverflow
Solution 5 - JavaLawrence DolView Answer on Stackoverflow
Solution 6 - JavaAtul SomanView Answer on Stackoverflow
Solution 7 - JavaRavindra babuView Answer on Stackoverflow
Solution 8 - JavaDaniel WintersteinView Answer on Stackoverflow
Solution 9 - JavakrosenvoldView Answer on Stackoverflow
Solution 10 - JavaSteve KuoView Answer on Stackoverflow
Solution 11 - JavaYoni RoitView Answer on Stackoverflow
Solution 12 - JavaisapirView Answer on Stackoverflow
Solution 13 - JavaHari KrishnaView Answer on Stackoverflow
Solution 14 - JavaBadalView Answer on Stackoverflow
Solution 15 - JavaHugoTeixeiraView Answer on Stackoverflow
Solution 16 - JavaRamesh SubramanianView Answer on Stackoverflow
Solution 17 - JavaJohnnyView Answer on Stackoverflow
Solution 18 - JavaJim TView Answer on Stackoverflow
Solution 19 - JavarogerdpackView Answer on Stackoverflow
Solution 20 - JavaSuresh RamView Answer on Stackoverflow