How do I generate a Java thread dump on Windows?

Solution Verified - Updated -

Environment

  • Java
  • Microsoft Windows

Issue

  • How to get a thread dump from a Java process running on a Windows machine?
  • Can I get a thread dump/stack trace from a Windows JVM?
  • I need a thread dump from a Windows JVM which was started as a service.

Resolution

JVM Started from Console

If the JVM was started from a command prompt or console, the thread dump can be triggered by selecting the console window in which the JVM is running and pressing CTRL+Break.

If console output has not been redirected, the thread dump will be printed to the console. This output is normally very large and will overflow the console window's scroll-back buffer. Therefore, it may be necessary to increase the size of the scroll-back buffer to capture the entire thread dump.

Alternatively, the JVM can be started with its output redirected to a file. If the JVM is being launched by a shell script (.bat or .cmd file), console output can normally be redirected by adding > console.log 2>&1 to the end of the command used to launch the shell script. For example:

run.bat > C:\MyLogs\console.log 2>&1

In the above case, the console's standard output and standard error display is being redirected to a file named console.log located in  C:\MyLogs. If console.log already exists, it will be overwritten.

If the JVM is not being started by a shell script, or the shell script is being launched by another process, the same redirection can be added directly to the command that is starting the JVM. For example:

java MyJavaClass > C:\MyLogs\console.log 2>&1
JVM Started As Windows Service

Because no console is associated with the JVM process when it has been started as a Windows Service, it is necessary to redirect the JVM's output to a file to view the thread dump. If the method used to invoke the JVM service does not have the capability of capturing the output to a file, the output can be redirected as discussed in the section above.

The user executing jstack.exe must be the same user who owns the JVM process or have sufficient privileges to access it (and Administrator for example). On Windows Server 2008R2, admin users do not have sufficient privileges to access services which run as Local System, so you will need to use the PsExec.exe tool (http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx) to execute jstack.exe.

jstack requires the Java Process ID. To determine the Java PID:

  1. Right-click an empty area on the task bar and select Task Manager.
  2. Select the Processes tab.
  3. If you are not the same user who owns the JVM process, check Show processes from all users at the bottom of Task  Manager.
  4. Select View > Select columns... from the menu bar.
  5. Check PID (Process Identifier).
  6. Click the OK button.
  7. Click on the Image Name column to resort the processes by name.
  8. Locate the process named "java". If there are multiple Java processes, locate the relevant one.
  9. Note of the number in the PID column.
    Or
    you can also attempt using your JDK's jps command to find and list running java processes:
jps -l -m -v

Example usage for a pid with the value 4180:

C:\PSTools>psexec -s c:\Java\jdk1.7.0_51\bin\jstack.exe -l 4180 >dump.txt

PsExec v2.11 - Execute processes remotely
Copyright (C) 2001-2014 Mark Russinovich
Sysinternals - www.sysinternals.com

Starting c:\Java\jdk1.7.0_51\bin\jstack.exe on KDC2008...
c:\Java\jdk1.7.0_51\bin\jstack.exe exited on KDC2008 with error code 0.

Note:
-s Run the remote process in the System account.
the path to jstack must be fully qualified

Use -accepteula to Suppress the display of the license dialog. This will be require for the first run of the psexec - Ref

The output will be redirected to a file "dump.txt". If you see an error like below from psexec, be sure that when launching the console you "run as administrator" and run psexec in this console:

Couldn't install PSEXESVC service:
The handle is invalid.
Sun JDK
  • If using Sun JDK 1.6 or later, use jstack. This avoids the issues related to generating the SIGQUIT signal and capturing the console or JVM output. It is also useful when redirecting standard out to a file is problematic  for some reason (e.g. it is not desirable to restart the JVM just to  redirect standard out). Execute the following, passing in the Java process ID:

    jstack -l JAVA_PID > jstack.out
    

Note: There are known bugs related to using other jstack options (e.g. -F, -m, etc.) and/or thread dump tools are not able to parse the output, so if any other options besides -l are proposed, be sure to test capturing and parsing the output.

  • If copying the thread dump from a console window, the first line of the  thread dump will be "Full thread dump".
  • Using CTRL+Break will not work with the -Xrs JVM argument, since the -Xrs flag causes SIGQUIT and SIGWAITING signals to be ignored.
  • WARNING: If the JVM process was started with the -Xrs JVM argument, sending it a CTRL+Break signal will result in the process being terminated.
  • WARNING: If the JVM process was started without the -Xrs JVM argument but was started as a Windows Service, logging off the machine may result in the JVM being terminated by Windows.

The attached script can also be used to generate multiple thread dumps at preset intervals using jstack.

Attachments

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

1 Comments

The user executing SendSignal.exe must be the same user who owns the JVM process or have sufficient privileges
to access it. On Windows Server 2008r2, admin users do not have sufficient privileges to access services which
run as Local System, so you will need to use the PsExec (see below) to run SendSignal or jstack.
Suggestion: Explain whether you need to use psexec to run jstack as the same user as which is running the jboss service, or you should use psexec to run jstack as the local system user.
The current sentence makes it seem like the first is expected (psexec -u ...), but google tells me you need to run as local system account (psexec -s ...).
For me both of them do not work btw.