从JVM进行线程转储
线程转储是Java虚拟机(JVM)中当前处于活动状态的所有Java线程的列表。 本文介绍了在Adobe Experience Manager中从JVM获取线程转储的几种方法。
描述 description
环境
Adobe Experience Manager
问题/症状
如何从Linux、UNIX或Windows上的JVM获取线程转储?
线程转储是Java虚拟机(JVM)中当前处于活动状态的所有Java线程的列表。
有多种方法可从JVM进行线程转储。 强烈建议进行1个以上的线程转储。 好的方法是定期进行10次线程转储(例如,每10秒转储一次线程转储)。
解决方法 resolution
步骤1:获取Java进程的PID
要获得线程转储,您需要的第一项信息是Java进程的PID。
Java JDK附带jps命令,该命令列出了所有Java进程ID。 可以像这样运行此命令:
jps -l 70660 sun.tools.jps.Jps 70305
注意: 在Linux和UNIX中,您可能必须以sudo -u user jps -l
身份运行此命令,其中“user”是Java进程运行时所使用的用户的用户名。
如果此操作不起作用,或者您仍然找不到Java进程,(路径未设置、未安装JDK或较旧的Java版本),请使用
- UNIX、Linux和Mac OS X:
ps -el | grep java
- Windows:按Ctrl+Shift+Esc打开任务管理器并查找Java进程的PID
步骤2:从JVM请求线程转储
jstack
如果已安装/可用,我们建议使用 jstack 工具。 它将线程转储打印到命令行控制台。
要使用jstack获取线程转储,请运行以下命令:jstack -l <pid>
您可以使用控制台输出重定向/附加指令将连续的线程转储输出到文件:jstack -l <pid> >> threaddumps.log
注意:
-
jstack工具自JDK 1.5起便已可用(对于Windows上的JVM,仅在JDK 1.5和JDK 1.6的某些版本中可用)。
-
即使启用了
-Xrs
jvm参数,jstack仍然有效 -
无法使用JDK 1.6中的jstack工具从JDK 1.5上运行的进程获取线程转储。
-
在Linux和UNIX中,您需要以拥有java进程的用户身份运行命令:
sudo -u java-user jstack -l <pid>
(
<
java-user>
应替换为Java进程作为其运行的用户的ID) -
在Windows中,如果运行jstack并收到错误“没有足够的存储空间来处理此命令”,则必须以Windows SYSTEM用户或拥有Java进程的用户身份运行jstack。 你可以使用psexec执行此操作,你可以在此处下载它。 要以SYSTEM用户身份运行jstack,请使用如下命令:
psexec -s jstack <pid> >> threaddumps.log
如果无法在服务器上安装psexec,则可以创建包含该命令的.bat文件,并使用Windows任务计划程序运行该文件(以其他用户的身份)。
-
如果Java进程没有响应,则有时使用选项 -J-d64(在64位系统上)会有所帮助,例如:
jstack -J-d64 -l <pid> >> threaddumps.log
-
如果jstack命令(
jstack -l <pid> >> threaddumps.log
)引发以下错误[
1]
,则以拥有java进程的用户身份运行该命令。 例如:sudo -u sling jstack -l <pid> >> threaddumps.log
Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 22893: Operation not permitted
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 22893: Operation not permitted
...
Caused by: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 22893: Operation not permitted
...
sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.run(LinuxDebuggerLocal.java:138)
JSTACK脚本
这是一个脚本(根据eclipse.org上的脚本改写),将使用jstack进行一系列线程转储。 它还使用top命令来获取线程级别cpu的使用情况。
像这样运行:
sudo -u <user> jstackSeries.sh
<pid> <aemserveruser> <count> <delay>
例如:sudo -u aemuser jstackSeries.sh 1234 aemserveruser 10 3
- 1234 是Java进程的PID
- cq5serveruser 是Java进程运行的Linux或UNIX用户
- 10 为要转储的线程数
- 3 是每个转储之间的延迟
注意: 顶部输出具有十进制格式的本机线程ID,而jstack输出具有十六进制格式的nid。 通过将线程ID转换为十六进制,可以将高cpu线程从顶部输出匹配到jstack输出。
除了上述脚本之外,我们还在github🔗上提供了类似的Windows Powershell脚本和AdobeAEM特定脚本。
获取线程转储的替代方法
如果 jstack 工具不可用,则您可以按照以下方式执行线程转储:
注意: 如果启用了命令行参数-Xrs
,则某些工具无法从JVM进行线程转储。 如果您在进行线程转储时遇到问题,请查看此选项是否已启用。
UNIX、Mac OS X和Linux(JDK 1.4或更低版本)
在UNIX、Mac OS X和Linux上,您可以向Java进程发送QUIT信号,以告知其将线程转储输出到标准输出。
-
运行此命令以执行此操作:
kill -QUIT <pid>
您可能需要以
sudo -u user kill -QUIT <pid>
身份运行此命令,其中“user”是Java进程正在以的用户身份运行。 -
如果您使用
crx-quickstart/server/start
脚本启动CQSE,则线程转储将输出到crx-quickstart/server/logs/startup.log
。 如果您使用的是第三方应用程序服务器,如JBoss、WebSphere、Tomcat或其他服务器,请参阅服务器的文档以了解标准输出将指向哪个文件。
Windows:
JDK 1.X
- 下载javadump.exe (附于下方)。
- 使用以下三个参数启动JVM(它们的顺序必须正确):
-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile= C:\temp\jvmoutput.log
- 按Ctrl+Shift+Esc打开“任务管理器”。
- 查找Java进程的PID。
- 从命令行运行:
javadump.exe <pid>
- 线程转储将显示在步骤2中提到的
jvmoutput.log
文件中。
JDK 1.6
使用插件从 jconsole 工具获取线程转储: [
0]
以下是如何请求线程转储的:
- 将以下参数添加到运行Communique的jvm中:
Dcom.sun.management.jmxremote
- 下载并安装JDK 1.6(如果尚未完成)。
- 下载并解压缩线程转储分析器实用程序。
[
1]
- 运行JDK 1.6的
jconsole.exe
:jconsole.exe -pluginpath /path/to/file/tda.jar
- 单击 线程转储 选项卡。
- 单击 请求线程转储 链接。
注意: 如果您正在运行AEM 6.x,并且希望观察正在运行的线程,则可以请求http://<host>:<port>/system/console/status-Threads
以获取线程列表。 但是,请注意,这些线程转储将不适用于samurai或tda等线程转储分析工具。
应用于:
在JVM中运行的所有Adobe产品
线程转储分析工具
Microsoft文档中的Sysinternals中的[
0]
PsExec v2.42。
[
1]
TDA - Github.com上irockel/tda上的线程转储分析器。
FastThread上的[
2]
Java线程转储分析器。
在IBM支持助手文档上,[
3]
用于Java的IBM线程和监视器转储分析器。