(点击
上方公众号
,可快速关注)
来源:飒然Hang
链接:rowkey.me/blog/2016/11/16/java-trouble-shooting/
最近看到了大量关于java性能调优、故障排查的文章,自己也写了一篇Java调优经验谈。接着此篇文章,其实一直打算写写一些常用调优工具以及它们的惯常用法的。后来在http://java-performance.info这个站点上看到了类似的一篇博文,自我感觉很有指导意义。于是决定翻译+重组织一下此篇文章:Java server application troubleshooting using JDK tools。
引言
在Java世界中,我们的很多开发工作从编码、调试到调优都在使用GUI工具。我们经常尝试在本地构建一套和线上一样的环境从而使得问题能够重现,进而使用我们常用的工具来排查定位故障。但不幸的是,很多情况下是无法在本地重现线上问题的。例如,我们没有权限获取真实客户端提交到线上服务端的数据。
由此,很多时候都是需要远程来排查线上服务器上发生的问题。但是如果单单只有一个JRE的话,你也不可能有合适的办法来进行排查。你需要JDK或者第三方的工具。有时候使用JDK提供的工具就是最可取的方案,毕竟,在线上环境使用第三方工具有时候会牵扯到权限的问题。
一般情况下,在线上环境安装JDK发布版本可以让排查进行地更高效。建议安装使用最新的Java7/8 JDK或者构建与线上JRE匹配的一些工具(原文作者不建议安装jdk的发布版本,而是建议根据实际需求逐渐地安装其中的工具)。
问题排查场景
获取正在运行的JVM列表
为了开始排查工作,我们首先需要获取正在运行的jvm进程列表,包括进程id、命令行参数等。有时候仅仅这一步就可以定位到问题,例如,同样的app实例被重复启动在并发做同样的事情(破坏输出文件、重新打开sockets或者其他愚蠢的事情)。
使用jcmd不加任何参数即可获取jvm进程列表
25691 org.apache.catalina.startup.Bootstrap start
20730 org.apache.catalina.startup.Bootstrap start
26828 sun.tools.jcmd.JCmd
3883 org.apache.catalina.startup.Bootstrap start
使用jcmd help能够获取某个jvm进程其他可用的诊断命令。例如:
[root@test-172-16-0-34-ip ~]# jcmd 3883 help
3883:
The following commands are available:
VM.commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
Thread.print
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help
输入jcmd 可以运行一个诊断命令或者获取到参数错误信息。
[root@test-172-16-0-34-ip ~]# jcmd 3883 GC.heap_dump
3883:
java.lang.IllegalArgumentException: Missing argument for diagnostic command
通过jcmd help 你能够获取此诊断命令更多的信息。如下是GC.heap_dump命令的help。
[root@test-172-16-0-34-ip ~]# jcmd 3883 help GC.heap_dump
3883:
GC.heap_dump
Generate a HPROF format dump of the Java heap.
Impact: High: Depends on Java heap size and content. Request a full GC unless the '-all' option is specified.
Syntax : GC.heap_dump [options]
Arguments:
filename : Name of the dump file (STRING, no default value)
Options: (options must be specified using the
or
=
syntax)
-all : [optional] Dump all objects, including unreachable objects (BOOLEAN, false)
Java堆的DUMP
jcmd提供了输出HPROF格式的堆dump接口。运行jmcd GC.heap_dump 即可。注意这里的FILENAME是相对于运行中的jvm目录来说的,因此避免找不到dump的文件,这里推荐使用绝对路径。此外,也建议使用.hprof作为输出文件的扩展名。