Windows上的Java堆栈跟踪

Windows上的Java堆栈跟踪,java,jstack,Java,Jstack,我需要获取在使用windows的客户机上运行的JVM进程的堆栈跟踪 客户端安装了JRE,但没有安装JDK 我想使用JStack,但它还没有安装,我们无法在客户机上安装JDK。我还尝试从Java Webstart会话中使用Adaptej stack trace产品,但这不起作用,因为我们在远程登录时遇到了一个错误,即不是以指定PID启动应用程序的会话 基本上,我想要一种不安装JDK而安装JStack的方法。您可能想要使用它,它正是为此目的而设计的。您可以通过远程访问使用它吗?JDK和相关工具可以正

我需要获取在使用windows的客户机上运行的JVM进程的堆栈跟踪

客户端安装了JRE,但没有安装JDK

我想使用JStack,但它还没有安装,我们无法在客户机上安装JDK。我还尝试从Java Webstart会话中使用Adaptej stack trace产品,但这不起作用,因为我们在远程登录时遇到了一个错误,即不是以指定PID启动应用程序的会话


基本上,我想要一种不安装JDK而安装JStack的方法。

您可能想要使用它,它正是为此目的而设计的。

您可以通过远程访问使用它吗?

JDK和相关工具可以正常工作,无论“安装”与否,只要将其压缩并解压缩到临时目录,您应该能够运行jstack。(无需修改路径或JAVA_主页)。只需确保您使用的版本与客户端运行应用程序时使用的JRE版本相同。至少在JConsole的情况下,如果版本不同,它似乎会大惊小怪。我不确定jstack是否也有同样的行为


我不是说这是一个理想的解决方案,只是说它会起作用。我认为jdigital和Eddie的建议是最好的先下注,即使这不会像运行安装程序那样干扰现有的java安装,客户也可能不同意

jstack和jps是JDK的tools.jar的一部分。 将jstack附加到进程中还需要attach.dll

当然,tools.jar和attach.dll不是JRE的一部分

为了使jstack在没有JDK(主要是Windows)的系统上工作,我通常执行以下操作

  • 从JDK复制tools.jar和attach.dll并放到某个位置 在目标系统上。示例:到c:\temp\jstack
  • 编写一个bat脚本,使用JRE手动调用它
  • 例如,创建bat文件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 %*
    
    与jps类似,创建一个包含以下内容的jps.bat

    设置JRE=c:\jrefolder

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

    jstack.bat -l <pid>
    
    jstack.bat-l
    

    希望这有帮助。

    要仅使用JRE获得线程转储,您需要来自相同Java版本的JDK的tools.jar和attach.dll。将其安装到某处,并将其复制到jre中。必须是相同的版本

    如果需要转储在系统帐户下运行的进程,可以使用Windows sysinternals psexec.exe访问该进程。将其复制到JRE bin或路径中的某个位置

    此批处理文件将堆栈转储写入具有datetime文件名的文件,因此可以轻松地进行多个跟踪并进行比较

    线程.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
    

    如果您希望使用JDK的板载工具,并且同时希望具有最小的(即不包括复制整个JDK)和方便的(即不使用自定义的
    .bat
    )解决方案,这对我很有用(在Java 1.8上试用过):

    创建一个空文件夹(
    $DEST
    如下)并将以下文件(从JDK
    $JDK_HOME
    )复制到
    bin
    lib
    文件夹中,如下所示:

    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
    
    然后将其压缩并复制到运行兼容JRE的目标计算机上


    现在应该可以从
    bin
    文件夹运行
    jps
    jstack
    ,就像从原始JDK运行它们一样。

    仅供参考,“kill-3pid”将导致Unix/Linux jre将整个线程堆栈跟踪转储到stdout。非常非常方便。通过查看SendSignal网页,如果应用程序作为服务运行(或者以-Xrs(减少信号使用))作为参数,我会非常小心。如果是这样,Java的ctrl+break处理将被禁用,应用程序将在收到此信号时终止。实际上,我使用SendSignal.exe来实现JRE作为服务运行的堆栈转储。是的,如果有人运行“java-Xrs…”,那么他们可能会在SendSignal.exe上遇到问题。解决办法是你不能同时做这两件事。选择一个。使用-Xrs或使用SendSignal.exe导致堆栈转储。你的选择。我用SendSignal做了一个测试,我的java进程在一个打开的控制台窗口中运行,结果成功了,我在控制台窗口中看到了一个错误。但是,当jvm进程在后台运行时,我在哪里可以从堆栈跟踪中获得打印结果呢?堆栈跟踪将到达进程的标准输出所在的位置。理想情况下,这会转到某个日志文件中。jps以这种方式工作正常,但jstack失败,出现“java.util.ServiceConfigurationError:com.sun.tools.attach.spi.AttachProvider:Provider sun.tools.attach.WindowsAttachProvider无法实例化”@EmmanuelBourg您确定attach.dll存在于-Djava.library.path=中提到的路径中吗?请确认。将进程附加到jstack需要attach.dll。是的,但我试图附加到以管理员身份运行的进程,而我的shell没有提升的权限,这可能解释了问题。