环境
- 爪哇
- Linux和大多数类似Unix的环境
问题
- 在Linux上运行时,如何在JBoss中生成线程转储?
- 如何在Linux上生成JBoss堆栈跟踪?
- 如何将kill -3的输出重定向到文件?
- JBoss的cpu使用率很高,冻结,挂起或不释放空闲线程,如何获取线程转储进行故障排除?
- JMS消息丢失了,如何生成线程转储以进行调查?
- 无法在server.log或console.log中使用Kill -3进行线程转储
解析度
免责声明:此处包含的指向外部网站的链接仅出于方便目的而提供。红帽尚未审查这些链接,并且对其内容或其可用性不承担任何责任。包含任何指向外部网站的链接并不意味着Red Hat认可该网站或其实体,产品或服务。您同意Red Hat对因您使用(或依赖)外部站点或内容而导致的任何损失或费用不承担任何责任。
选择以下方法之一在Unix上生成Java线程转储:
- 选项1:OpenJDK / Sun JDK
- 选项2:
kill -3
Linux脚本(非连续) - 选项3:
kill -3
Linux脚本(连续) - 选项4:JBoss EAP参数
- 选项5:
jstack
Linux脚本(连续) - 选项6:IBM J9
注意:通常,只要捕获线程转储,就会提供gc日志记录。过多的gc可能会导致线程问题,因此gc和线程转储分析是并驾齐驱的。
选项1:OpenJDK / Sun JDK
使用jps -lv
可以找到Java进程ID发放kill -QUIT
或kill -3
。
确保-Xrs
未使用JVM选项,因为它会导致忽略SIGQUIT
和SIGWAITING
信号。正在运行会kill -3
向SIGQUIT
JVM发送信号,因此使用此选项将导致kill -3
被忽略。请参阅Java应用程序启动器。
如果使用OpenJDK或Sun JDK 1.6或更高版本,则使用jstack
选项。当出于某种原因将标准重定向到文件有问题时,这很有用(例如,不希望仅出于将标准重定向到JVM而重新启动JVM)。输入Java进程ID,执行以下操作:
jstack -l JAVA_PID > jstack.out
注意Java进程的进程ID号码(例如,使用top
中,grep
上ps -axw
,等)并发送一个QUIT
信号给过程中与kill -QUIT
或kill -3
命令1。例如:
kill -3 JAVA_PID
选项2:kill -3
Linux脚本(非连续)
下载threaddump_linux.sh.tar.gz
或threaddump_solaris.sh.tar.gz
,然后解压缩脚本。使脚本可执行chmod 755
。
该脚本将捕获一系列6个线程转储,它们间隔20秒(可以根据需要进行修改),并传入Java进程ID作为参数。例如:
Linux: sh ./threaddump_linux.sh JAVA_PID
Solaris: bash ./threaddump_solaris.sh JAVA_PID
确保在问题发生之前测试脚本,以确保脚本在您的环境中正常运行。
选项3:kill -3
Linux脚本(连续)
下载threaddump_linux-continuous.sh.tar.gz
或threaddump_solaris-continuous.sh.tar.gz
,然后解压缩脚本。使脚本可执行chmod 755
。
它将捕获相距20秒(根据需要进行修改)的线程转储,并将Java进程ID作为参数传入。例如:
Linux: sh ./threaddump_linux-continuous.sh JAVA_PID
Solaris: bash ./threaddump_solaris-continuous.sh JAVA_PID
确保在问题发生之前测试脚本,以确保脚本在您的环境中正常运行。
选项4:JBoss EAP参数
使用以下命令启动JBoss实例,然后用于kill -3
生成线程转储。
如果Java应用程序使用记录控制台输出的服务脚本启动,则线程转储将在控制台日志中。否则,stdout
在启动时重定向到文件。
nohup $JBOSS_HOME/bin/run.sh -c yourinstancename $JBOSS_OPTS >> console-$(date +%Y%m%d).out 2>&1 < /dev/null &
kill -3 JAVA_PID
这会将您的输出/转储重定向到上述命令中指定的文件控制台。
选项5:jstack linux脚本(连续)
下载linux_jstack-continuous.tar.gz
并解压缩脚本。chmod 755
使用Jstack使其可执行脚本。它将使用jstack捕获一系列6个线程转储,它们间隔20秒(根据需要进行修改),并传入Java进程ID作为参数。确保JAVA_HOME
在此脚本中进行设置。它会jstack_threaddump.out
在执行该脚本的目录中生成一个名为的文件。例如:
./threaddump_linux_jstack-continuous.sh JAVA_PID
选项6:IBM J9
IBM J9拥有自己的监视工具,即Java-TMDA的IBM线程和监视器转储分析器。但是,kill -3 PID
仍然可以用来生成线程转储,如请参阅选项1:OpenJDK / Sun JDK kill -3
部分中所述。
可以在OpenJ9 Docs-Java Dumps中找到更多信息。
笔记
- 使用
ps aux
命令(R
或列中的S
状态STAT
)验证Java进程是否仍在运行。例如,jstack -F <pid>
将目标Java进程置于“跟踪停止”(T)状态。处于(T)状态的线程将接收线程转储的信号;但是,输出将延迟到该过程继续进行。 - 您需要确保
jstack
从与Java进程相同的用户处执行命令。请参阅在执行jstack / jmap / jcmd且无法生成线程转储/堆转储时获取“无法打开套接字文件”消息,以获取更多详细信息。 - 存在与使用其他
jstack
选项(例如-F
,-m
等)有关的已知错误和/或线程转储工具无法解析输出,因此,如果-l
建议使用除其他选项之外的其他选项,请确保测试捕获和解析输出。 - 在某些情况下,运行jstack可能会影响性能。据报道,在某些情况下运行jstack时,可以观察到响应时间变慢。
- 如果要进行线程转储以标识哪些Java线程消耗了较高的cpu,请参见如何在Linux / Solaris上确定Java线程的CPU使用率,并在本文中使用随附的示例脚本。
JBoss EAP 5.x
要stdout
在启动时重定向到文件:
sh run.sh > console.log 2>&1
如果重定向时遇到问题stdout
,请修改$JBOSS_HOME/bin/run.sh
并更改该行:
org.jboss.Main "$@"
阅读:
org.jboss.Main "$@" > console.log
正常保存并重新启动JBoss。现在kill -3
还是kill -QUIT
应该在文件中创建一个线程转储console.log
。
JBoss EAP 7.x / 6.x
建议使用jstack
。请参阅选项5:jstack
Linux脚本(连续)。
JBoss保险丝6
如果要从子容器捕获线程转储,请注意该过程与根容器不同。选择用于运行脚本的PID之前,请确保使用“ ps”或类似的命令检查进程ID(PID)。例如:
ps -ef | grep child1
testusr 27803 1 0 09:41 pts/1 00:00:12 /usr/java/jdk1.7.0_21/jre/bin/java -server ... -Dkaraf.home=/home/testusr/apps/product-distributions -Dkaraf.base=/home/testusr/apps/product-distributions/instances/child1 org.apache.karaf.main.Main
有关的
如何确定Linux / Solaris上Java线程的CPU使用率高
-
注意:
kill -3
命令不会直接从命令行产生输出到文件。相反,它将产生console output
对其调用的过程的输出。对于JBoss EAP域模式服务器,默认情况下应在主机控制器日志中捕获其控制台输出。 ↩
附件