内容简介:Java与C++之间有一堵由内存分配和垃圾收集技术所围成的“高墙”,墙里面的人想出去,墙外面的人想进来。在给一个系统定位问题的时候,知识、经验是关键基础,而工具是运用知识去处理数据的手段,这里的数据在JVM中包括:运行日志、异常堆栈、GC日志、线程快照(threaddump/javacore文件)、堆转储快照(headdump/hprof文件)等。经常使用适当的虚拟机监控和分析的工具可以加快我们分析数据、定位解决问题的速度。但是下面介绍的所有工具,都只是对知识技能的一层“封装”,吃透底层原理才是最重要的,工
Java与C++之间有一堵由内存分配和垃圾收集技术所围成的“高墙”,墙里面的人想出去,墙外面的人想进来。
概述
在给一个系统定位问题的时候,知识、经验是关键基础,而 工具 是运用知识去处理数据的手段,这里的数据在JVM中包括:运行日志、异常堆栈、GC日志、线程快照(threaddump/javacore文件)、堆转储快照(headdump/hprof文件)等。经常使用适当的虚拟机监控和分析的工具可以加快我们分析数据、定位解决问题的速度。但是下面介绍的所有工具,都只是对知识技能的一层“封装”,吃透底层原理才是最重要的,工具的使用是次要的。
JDK命令行工具
一般来说,Java开发人员在初学 Java 的时候就知道有 java.exe
和 javac.exe
两个命令行工具,这是最开始我们写 Hello World
的时候用到的,但是却并不是所有Java程序员都知道除了这两个命令行工具外,JDK自带的 bin
目录下的其它很多 exe
工具的数量和功能是在不断的增加和提升的。
由于我个人使用的是 JDK1.8
版本,所以我们以windows下 JDK1.8
版本下 bin
目录工具为例,如果是 linux 或者macOS可能看到的不太一样。
其中细心的人可以发现好像大多数工具都是17KB,嘿,难道是JDK开发团队在刻意跟我们炫耀高超编程技巧?其实当然不是,这只是因为上面的exe命令行工具大多数都是 jdk/lib/tools.jar
工具的一层很薄的封装而已,其中主要的功能实现都是在 tools
类库中实现的。
那么为啥要采用java代码来实现这些监控工具呢?
其实啊,主要是因为实际应用程序部署到生产环境后,无论是直接接触物理服务器还是远程Telnet到服务器上都可能受到限制,而借助 tools.jar
类库里面的工具,我们就可以直接在应用程序中实现强大的监控分析工具。
如果使用的是JDK1.5及之前版本的JDK的话,在程序启动的时候需要添加参数”-Dcom.sun.management.jmxremote”来开启JMX管理功能,因为其中监控工具大多数都是基于JMX的,而如果是JDK1.6之后的版本,那么JMX管理是默认开启的,即不需要手动添加参数。
常用的JDK监控和故障处理工具
名称 | 主要作用 |
---|---|
jps(JVM Process Status Tool) | 显示指定系统内所有的HotSpot虚拟机进程 |
jstat(JVM Statistics Monitoring Tool) | 用于收集HotSpot虚拟机各方面的运行数据 |
jinfo(Configuration Info for Java) | 显示虚拟机配置信息 |
jmap(Memory Map for Java) | 生成虚拟机的内存转储快照(heapdump文件) |
jhat(JVM Heap Dump Browser) | 用于分析heapdump文件,会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果 |
jstack(Stack Trace for Java) | 显示虚拟机的线程快照 |
jps:虚拟机进程状况工具
ps取名其实和Unix的ps命令一样,也就是用来列出正在运行的虚拟机进程,并显示虚拟机执行主类,其实在windows下或者linux下ps命令也可以查询到虚拟机进程的id,但是如果同时启动了多个虚拟机进程,且无法通过进程名称定位时,那就只能依赖jps命令显示主类来查询虚拟机进程了。
jps命令格式:
jps [options] [hostid]
用法比较简单,比如我在本地启动了两个虚拟机进程,主类名称分别是 cn.bestzuo.MultiThread
和 cn.bestzuo.SynAddRunnable
,在使用 jps -l
命令查看进程:
C:\Program Files\Java\jdk1.8.0_191\bin> jps -l +12256 cn.bestzuo.SynAddRunnable 11012 org.jetbrains.jps.cmdline.Launcher +4696 cn.bestzuo.MultiThread 5480 sun.tools.jps.Jps 8408
上面绿色的两个进程就是虚拟机启动的进程,前面的数字表示进程id。
那么后面的 -l
是选择使用的参数,jps命令可以使用的参数如下:
选项 | 作用 |
---|---|
-q | 只输出LVMID,省略主类的名称 |
-m | 输出虚拟机进程启动时传递给主类main()函数的参数 |
-l | 输出主类的全名,如果进程执行的是jar包,输出Jar路径 |
-v | 输出虚拟机进程启动时JVM参数 |
jstat:虚拟机统计信息监视工具
jstat用于监视虚拟机各种运行状态信息的命令行工具,它可以显示本地或者远程虚拟机中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
jstat命令格式为:
jstat [option vmid [interval[s|ms] [count]] ]
对于命令格式中的VMID和LVMID需要特别说明一下,如果是本地虚拟机进程,那么VMID和LVMID是一致的,如果是远程虚拟机进程,那么VMID的格式应该是:
[protocol:][//]lvmid[@hostname[:port]/servername]
其中参数interval和count代表查询间隔和次数,如果省略这两个参数,说明只查询一次。
假设需要每250毫秒查询一次进程id为2764垃圾收集情况,一共查询20次,那么命令应该是:
jstat -gc 2764 250 20
选项option代表用户想要查询的虚拟机信息,主要分三类:类装载、垃圾收集和运行期编译情况。
选项 | 作用 |
---|---|
-class | 监视类装载、卸载数量、总空间以及类装载所耗费的时间 |
-gc | 监视java堆状况,包括Eden区、两个Survivor区、老年代、永久代容量、已用空间、GC时间合计等信息 |
-gccapacity | 监视内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间 |
-gcutil | 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比 |
-gccause | 与-gcutil工具一样,但是会额外输出导致上一次GC产生的原因 |
-gcnew | 监视新生代GC状况 |
-gcnewcapacity | 监视内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间 |
-gcold | 监视老年代GC状况 |
-gcoldcapacity | 监视内容与-gcold基本相同,输出主要关注使用到的最大、最小空间 |
-gcpermcapacity | 输出永久代使用到的最大、最小空间 |
-compiler | 输出JIT编译器编译过的方法、耗时等信息 |
-printcompilation | 输出已经被JIT编译过的方法 |
由于jstat监视选项太多,因此只测试一下其中一项观察结果,依然测试主类 cn.bestzuo.SyncAddRunnable
主类,我们可以看到如下结果:
C:\Program Files\Java\jdk1.8.0_191\bin> jstat -gcutil 12256 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 15.47 58.71 0.01 66.07 68.03 1 0.001 0 0.000 0.001
其中:
- S0、S1表示两个Survivor区,其中S1区使用了15.47%的空间
- E代表Eden区,即新生代使用了58.71%的空间
- O代表老年代,老年代中使用了0.01%的空间
- M表示元数据区,即metaspace,使用了66.07%的空间
- CCS表示压缩使用比例
- YGC即Minor GC,表示发生过一次
- YGCT表示新生代GC耗时时间
- FGC表示Full GC
- FGCT表示Full GC耗时时间
- GCT表示所有GC的总耗时
虽然jstat命令行工具不如后面提到的VisualVM直观,但是很多服务器管理员在没有GUI图形界面时,依然会使用该命令行工具来进行监视。
jinfo:Java配置信息工具
jinfo的作用是实时地查看和调整虚拟机各项参数。使用jps的-v参数可以查看虚拟机启动的时候显式指定的参数列表,但是如果想知道未被显示指定的参数的系统默认值,除了找资料外,就只能使用jinfo的-flag选项进行查询了。
jinfo的命令格式:
jinfo [option] pid
比如我们查询 CMSInitialingOccupancyFraction
参数值:
C:\Program Files\Java\jdk1.8.0_191\bin> jinfo -flag CMSInitiatingOccupancyFraction 12256 -XX:CMSInitiatingOccupancyFraction=-1
jmap:Java内存映像工具
jmap命令用于生成堆转储快照(一般称为headdump或dump文件)。如果不适用jmap命令,要想获取Java堆转储快照,也可以采取其它一些比较”暴力“的手段,比如使用 -XX:+HeapDumpOnOutOfMemoryError
参数,可以让虚拟机在OOM异常出现之后自动生成dump文件,通过 -XX:+HeapDumpOnCtrlBreak
参数则可以使用 [Ctrl]+[Break]
键让虚拟机生成dump文件,又或者在Linux系统下通过 Kill -3
命令发送进程退出信号”吓唬“一下虚拟机,也能拿到dump文件。
当然,jmap的作用并不仅仅是拿到dump文件,它还可以查询 finalize
执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的哪种收集器等。
和jinfo一样,jmap不少功能在windows平台下都是受限的,除了生成dump文件的-dump选项和用于查看每个类的实例、空间占用统计的-histo选项在所有操作系统都提供之外,其余选项只能在Linux/Solaris下使用。
jmap命令格式:
jmap [option] vmid
其中option选项的合法值和具体含义如下:
选项 | 作用 |
---|---|
-dump | 生成Java堆转储快照 |
-finliazeinfo | 显示在F-Queue中等待的Finalizer线程执行finalize方法的对象,只在Linux/Solaris平台下生效 |
-heap | 显示Java堆详细信息,如使用哪种垃圾收集器、参数配置、分代状况等,只在Linux/Solaris下有效 |
-histo | 显示堆中对象统计信息,包括类、实例数量、合计容量 |
-permstat | 以ClassLoader为统计口径显示永久代内存状态,Linux/Solaris下有效 |
-F | 当虚拟机进程对-dump选项没有响应时,可使用这个选项强制生成dump快照,Linux/Solris下有效 |
比如如下测试:
C:\Users\IcyFenix\jmap -dump:format=b,file=eclipse.bin 3500 Dumping heap to C:\Users\IcyFenix\eclipse.bin ... Heap dump file created
jhat:虚拟机堆转储快照分析工具
jhat命令主要与jmap命令搭配使用,可以分析jmap生成的堆转储快照。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后可以在浏览器中查看。
不过实际使用中,除非真的没有其它工具可以使用,否则一般不会直接使用jhat命令来分析dump文件,原因一是一般不会在部署应用程序的服务器上直接分析dump文件,即使可以这样做,也会尽量将dump文件复制到其它机器上进行分析,因为分析工作本身就是一个耗时并且消耗硬件资源的过程,既然能到其它机器上分析,那就没必要受到命令行工具的限制了;另外一个原因是jhat的分析功能较为简陋,其它更多的工具能分析出来的东西更多。
jstack:Java堆栈跟踪工具
jstack命令用于生成虚拟机当前时刻的线程快照(一般称之为yhreaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。线程出现停顿后可以使用jstack来查看各个线程间的调用堆栈,就可以知道没有响应的线程到底在后台做些什么,或者在等待什么资源。
jstack的命令格式:
jstack [option] vmid
jstack工具主要选项:
选项 | 作用 |
---|---|
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
-l | 除堆栈外,显示关于锁的附加信息 |
-m | 如果调用到本地方法的话,可以显示C/C++的堆栈 |
比如我们运行一段死锁的程序,然后查看其锁的信息:
PS C:\Program Files\Java\jdk1.8.0_191\bin> jstack -l 1328 2019-05-14 20:45:30 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.191-b12 mixed mode): 省略堆栈信息 ... "VM Thread" os_prio=2 tid=0x0000000017f68000 nid=0x18c0 runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000030e9000 nid=0x9e8 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000030ea800 nid=0x223c runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000030ec000 nid=0x16f4 runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000030ee800 nid=0x3af4 runnable "GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00000000030f1000 nid=0x1f94 runnable "GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00000000030f2000 nid=0x1440 runnable "VM Periodic Task Thread" os_prio=2 tid=0x0000000019ade000 nid=0x392c waiting on condition JNI global references: 12 Found one Java-level deadlock: ============================= "Thread-199": waiting to lock monitor 0x0000000019b95918 (object 0x00000000d5b7d5f0, a java.lang.Integer), which is held by "Thread-47" "Thread-47": waiting to lock monitor 0x00000000031cd708 (object 0x00000000d5b7d5e0, a java.lang.Integer), which is held by "Thread-58" "Thread-58": waiting to lock monitor 0x0000000019b95918 (object 0x00000000d5b7d5f0, a java.lang.Integer), which is held by "Thread-47" Java stack information for the threads listed above: =================================================== "Thread-199": at cn.bestzuo.SynAddRunnable.run(SynAddRunnable.java:13) - waiting to lock <0x00000000d5b7d5f0> (a java.lang.Integer) at java.lang.Thread.run(Thread.java:748) "Thread-47": at cn.bestzuo.SynAddRunnable.run(SynAddRunnable.java:14) - waiting to lock <0x00000000d5b7d5e0> (a java.lang.Integer) - locked <0x00000000d5b7d5f0> (a java.lang.Integer) at java.lang.Thread.run(Thread.java:748) "Thread-58": at cn.bestzuo.SynAddRunnable.run(SynAddRunnable.java:14) - waiting to lock <0x00000000d5b7d5f0> (a java.lang.Integer) - locked <0x00000000d5b7d5e0> (a java.lang.Integer) at java.lang.Thread.run(Thread.java:748) Found 1 deadlock.
注意:
在JDK1.5中, java.lang.Thread
类新增了一个 getAllStackTraces()
方法用于获取虚拟机中所有线程的 StackTraceElement
对象。使用这个方法可以通过简单的几行代码就完成 jstack
的大部分功能,在实际项目中不妨调用这个方法做一个管理员页面,可以随时使用浏览器来查看线程堆栈。
JDK可视化工具
JDK中除了提供大量的命令行工具外,还有两个功能非常强大的可视化工具: JConsole
和 VisualVM
,这两个是JDK的正式成员。
其中 JConsole
是jdk1.5时期就已经提供的虚拟机监控工具,而 VisualVM
在JDK1.6 Update7中才首次发布,现在已经成为Sun(Oracle)主力推动的多合一故障处理工具,并且已经从JDK中分离出来成为可以独立发展的开源项目。
上面两者由于是可视化工具,所以这里就不再赘述,内置功能相当于把前面提到的jdk命令行工具实现可视化。
以上所述就是小编给大家介绍的《JVM性能监控与故障处理工具》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- VCenter监控可实现精细故障排除
- AIOps智能监控在阿里巴巴故障
- 深入理解Java虚拟机之性能监控与故障处理工具
- 《深入理解Java虚拟机》-----第4章 虚拟机性能监控与故障处理工具
- 故障公告:Linux 内核故障导致网站宕机近 1 个小时
- 线上故障处理手册
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Advanced Web Metrics with Google Analytics
Brian Clifton / Sybex / 2008 / USD 39.99
Are you getting the most out of your website? Google insider and web metrics expert Brian Clifton reveals the information you need to get a true picture of your site's impact and stay competitive usin......一起来看看 《Advanced Web Metrics with Google Analytics》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
Base64 编码/解码
Base64 编码/解码