Java stack trace on Windows
Asked Answered
B

6

7

I need to get a stack trace for a JVM process running on a client machine that uses windows.

The client has the JRE installed but not the JDK.

I want to use JStack but it is not installed and we can't install a JDK on the client's machine. I also tried using AdaptJ stack trace product from a Java Webstart Session but that didn't work because we remote in and get an error about not being the session that started the application at a specified PID.

Essentially I want a way to install JStack without installing the JDK.

Byrnes answered 18/3, 2009 at 18:58 Comment(1)
Just for reference, "kill -3 pid" will cause a Unix/Linux jre to dump the entire thread stack trace to stdout. Very, very, very handy.Neoclassic
S
5

You probably want to use SendSignal, which was designed for exactly this purpose.

Scythe answered 18/3, 2009 at 18:59 Comment(5)
From looking at the SendSignal webpage, I would be careful if the app is being run as a service (or otherwise has -Xrs (reduce signal usage)) as an argument. If so, Java's ctrl+break handling is disabled and the application will terminate when it receives this signal.Zonda
Actually, I use SendSignal.exe for this purpose to cause a stackdump of a JRE running as a service. It works for me.Scythe
Yes, if someone runs "java -Xrs ..." then perhaps they'll have a problem with SendSignal.exe. The solution is that you can't do both at the same time. Choose one. Either use -Xrs or use SendSignal.exe to cause a stackdump. Your choice.Scythe
I tried a test with SendSignal where my java process was running in a open console window and it worked, i saw an error in the console window. But when a jvm process is running in the background where can i get the print out of the stack trace.Byrnes
The stack trace goes to wherever standard output of the process goes. Ideally, this goes to a log file somewhere.Scythe
Z
4

The JDK and associated tools work fine whether "installed" or not, if you just zip up and extract it to a temporary directory, you should be able to run jstack. (No PATH or JAVA_HOME modifications necessary). Just make sure you use the same version that corresponds to the JRE your client has the application running with. At least in the case of JConsole, it seems to fuss if the versions are different. I'm not sure if jstack behaves the same way.

I'm not saying this is the ideal solution, just that it would work. I think jdigital and Eddie's suggestions are better first bets, and even though this shouldn't interfere with an existing java installation the same way running the installer would, the customer may disagree regardless.

Zonda answered 18/3, 2009 at 19:35 Comment(0)
V
3

jstack and jps are part of tools.jar of the JDK. Also attach.dll is required to attach jstack to a process.

Ofcourse the tools.jar and attach.dll are not part of JRE.

To make jstack work on a systems which has no JDK (mostly Windows), I usually do the following.

  1. Copy tools.jar and attach.dll from JDK and put in to some location on the target system. Example: to c:\temp\jstack
  2. Write a bat script to manually invoke it using JRE.

For example, create a bat file jstack.bat:

set JRE=c:\jrefolder
"%JRE%\bin\java" -classpath "c:\temp\jstack\tools.jar" -Djava.library.path="c:\temp\jstack" sun.tools.jstack.JStack %*

Similarly for jps, create a jps.bat with following content.

set JRE=c:\jrefolder

"%JRE%\bin\java" -classpath "c:\temp\jstack\tools.jar" -Djava.library.path="c:\temp\jstack" sun.tools.jps.Jps %*

Usage:

jstack.bat -l <pid>

Hope this helps.

Variety answered 24/2, 2015 at 16:23 Comment(3)
jps works fine this way, but jstack failed with "java.util.ServiceConfigurationError: com.sun.tools.attach.spi.AttachProvider: Provider sun.tools.attach.WindowsAttachProvider could not be instantiated"Peripatetic
@EmmanuelBourg Are you sure that the attach.dll is present in the path mentioned in -Djava.library.path= ? Pls confirm. attach.dll is required to attach the process to jstack.Variety
Yes, but I was trying to attach to a process running as Administrator, and my shell didn't have elevated privileges, that probably explains the issue.Peripatetic
G
2

Would you be able to use JConsole via remote access?

Gebelein answered 18/3, 2009 at 19:5 Comment(0)
E
1

To get a thread dump with only a JRE you need tools.jar and attach.dll from the JDK of the same Java version. Install this somewhere and copy these into the jre. Must be identical version!

If you need a dump of a process running under the system account you can use the Windows sysinternals psexec.exe to gain access to the process. Copy this into the JRE bin or somewhere in the path.

This batch file writes the stack dump to a file with a datetime filename so multiple traces can be taken and compared easily.

Threads.bat

:: Creates a thread dump for the tomcat6.exe process 
:: saved in a timestamped filename and views it!
:: Jim Birch 20111128 rev 2015-10-12

::Required the following files to be placed in the jre/bin folder:
:: attach.dll  - From the Java JDK  (must be the same version)
:: tools.jar   - ditto
:: psexec.exe  - from Windows sysinternals

::cd to jre/bin
d:
cd \application\jre\bin

::build datetime filename
rem datetime from wmi.exe
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set dt0=%%I
rem  datetime string as YYYY-MM-DD-hhmmss
set dt=%dt0:~0,4%-%dt0:~4,2%-%dt0:~6,2%-%dt0:~8,6%
set ff=td-%dt%.txt
echo filename: %ff%

::PID of the process by named exe, eg, tomcat6    
for /F "tokens=2" %%I in ('TASKLIST /NH /FI "IMAGENAME eq tomcat6.exe"' ) DO SET PID=%%I
echo pid: %PID%

::combine above with jstack command
psexec -s jstack.exe -l %PID%  >>  %ff%

:: view result
start %ff%

::insert pause to debug or timer to review script operation
::ping localhost -n 20 >nul
::pause
Entrain answered 12/10, 2015 at 2:30 Comment(0)
T
0

If you want to use the on-board tools of the JDK and also want to both have a minimal (i.e., not including copying the whole JDK) and convenient (i.e. not invoking with a custom .bat) solution, this works for me (tried on Java 1.8):

Create an empty folder ($DEST below) and copy the following files (from the JDK $JDK_HOME) into bin and lib folders as follows:

Source                          -> Destination

$JDK_HOME/bin/jps.exe           -> $DEST/bin/jps.exe
$JDK_HOME/bin/jstack.exe        -> $DEST/bin/jstack.exe
$JDK_HOME/bin/jli.dll           -> $DEST/bin/jli.dll
$JDK_HOME/jre/bin/attach.dll    -> $DEST/bin/attach.dll
$JDK_HOME/lib/tools.jar         -> $DEST/lib/tools.jar

Then ZIP and copy this over to the destination machine running a compatible JRE.

You should be able to run jps and jstack from the bin folder now as you would run them from the original JDK.

Tohubohu answered 5/4, 2018 at 15:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.