1. 首页
  2. JVM系列

JVM 第五篇:命令行 JVM 故障处理工具

JVM 第五篇:命令行 JVM 故障处理工具

本文内容过于硬核,建议有 Java 相关经验人士阅读。

1. 引言

虽然我们前面介绍了各种图形化 JVM 故障处理工具,但是很多情况下,我们在处理问题的时候并没有图形化的操作环境可以使用,这时候,就需要用到 JDK 为我们提供的命令行工具了。

2. jps: 虚拟机进程状况工具

jps 绝对是使用频率最高的 JDK 命令行工具,它的作用是可以列出正在运行的虚拟机进程,并显示虚拟机执行主类( Main Class , main() 函数所在的类)名称以及这些进程的本地虚拟机唯一 ID ( LVMID , LocalVirtual Machine Identifier )。

命令格式:

jps [options ] [ hostid ] 

执行样例:

PS D:\> jps -l
5200 org.jetbrains.jps.cmdline.Launcher
16868 jdk.jcmd/sun.tools.jps.Jps
19368 org.jetbrains.idea.maven.server.RemoteMavenServer36

可以看到我本机,有三个 JVM 进程, 5200 和 19368 是软件 IDEA 的进程,从类名上是可以看出来的,还有一个是 jps 本身的这个 JVM 进程。

列举一些常用参数:

可选项 作用
-l 输出完全的包名,应用主类名,jar的完全路径名。
-q 仅输出 VM 标识符,不包括 classname , jar name , arguments in main method 。
-m 输出 main method 的参数。
-v 输出 JVM 参数。

3. jstat: 虚拟机统计信息监视工具

jstat(JVM Statistics Monitoring Tool) 是用于监视虚拟机各种运行状态信息的命令行工具。

位于 JDK 的 bin 目录下,主要利用 JVM 内建的指令对 Java 应用程序的资源和性能进行实时的命令行的监控,包括了对 Heap size 和垃圾回收状况的监控。

jstat 工具特别强大,有众多的可选项,详细查看堆内各个部分的使用量,以及加载类的数量。使用时,需加上查看进程的进程 id ,和所选参数。参考格式如下:

jstat -options 

可以列出当前 JVM 版本支持的选项,常见的有:

  • -class (类加载器)
  • -compiler (JIT)
  • -gc (GC堆状态)
  • -gccapacity (各区大小)
  • -gccause (最近一次GC统计和原因)
  • -gcnew (新区统计)
  • -gcnewcapacity (新区大小)
  • -gcold (老区统计)
  • -gcoldcapacity (老区大小)
  • -gcpermcapacity (永久区大小)
  • -gcutil (GC统计汇总)
  • -printcompilation (HotSpot编译统计)

比如我想查看一下我本地的 IDEA 进程的 GC 情况汇总,可以使用命令:

PS D:\> jstat -gcutil 5200
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT    CGC    CGCT     GCT
  0.00  43.29  20.83   0.08  97.05  93.67      1    0.003     0    0.000     -        -    0.003

查询结果表明:

我的 IDEA 的新生代 Eden 区( E ,表示 Eden )使用了 20.83% 的空间, 2 个 Survivor 区( S0 、 S1 ,表示 Survivor0 、 Survivor1 ),S0 是空的,而 S1 使用了 43.29% ,老年代( O ,表示 Old )使用了 0.08% 的空间,元空间( M , 表示 Metaspace )使用了 97.05% 的空间。

程序运行以来共发生 Minor GC ( YGC ,表示 Young GC ) 1 次,总耗时 0.003 秒,发生 Full GC ( FGC ,表示 Full GC )0 次,总耗时( FGCT ,表示 Full GC Time )为 0 秒,所有 GC 总耗时( GCT ,表示 GC Time )为 0.003 秒。

4. jinfo: Java 配置信息工具

jinfo(Configuration Info for Java)可以用来查看正在运行的 Java 应用程序的扩展参数,包括 Java System 属性和 JVM 命令行参数;也可以动态的修改正在运行的 JVM 一些参数。当系统崩溃时, jinfo 可以从 core 文件里面知道崩溃的 Java 应用程序的配置信息。

使用 jps 命令的 -v 参数可以查看虚拟机启动时显式指定的参数列表,但如果想知道未被显式指定的参数的系统默认值,除了去找资料外,就只能使用 jinfo 的 -flag 选项进行查询了。

jinfo 命令格式:

jinfo [option] pid

查询样例:

PS D:\> jinfo -flags 5200
VM Flags:
-XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=734003200 -XX:MaxNewSize=244318208 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC

5. jmap: Java 内存映像工具

jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为 heapdump 或 dump 文件)。

它也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。

jmap 命令格式:

jinfo [option] pid

option 可选的参数:

  • no option: 查看进程的内存映像信息,类似 Solaris pmap 命令。
  • heap: 显示 Java 堆详细信息
  • histo[:live]: 显示堆中对象的统计信息
  • clstats:打印类加载器信息
  • finalizerinfo: 显示在 F-Queue 队列等待 Finalizer 线程执行 finalizer 方法的对象
  • dump::生成堆转储快照
  • F: 当 -dump 没有响应时,使用 -dump 或者 -histo 参数. 在这个模式下, live 子参数无效.
  • help:打印帮助信息
  • J:指定传递给运行 jmap 的 JVM 的参数
PS D:\> jmap -dump:format=b,file=idea.bin 5200
Dumping heap to D:\idea.bin ...
Heap dump file created

6. jhat: 虚拟机堆转储快照分析工具

JDK 提供jhat(JVM Heap Analysis Tool)命令与 jmap 搭配使用,来分析 jmap 生成的堆转储快照。 jhat 内置了一个微型的 HTTP/Web 服务器,生成堆转储快照的分析结果后,可以在浏览器中查看。

使用命令为:

PS D:\> jhat idea.bin
Reading from idea.bin...
Dump file created Thu Oct 08 18:54:37 CST 2020
Snapshot read, resolving...
Resolving 147921 objects...
Chasing references, expect 29 dots.............................
Eliminating duplicate references.............................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

然后在浏览器上访问地址 http://localhost:7000/ 可以看到分析结果,不过这个分析工具一般没什么人会用,因为功能太过简陋了。

相比较而言,我们可以使用 VisualVM 或者 Eclipse Memory Analyzer 再或者 IBM HeapAnalyzer 等工具分析刚才 jmap 产生的 dump 文件。

7. jstack: Java 堆栈跟踪工具

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为 threaddump 或者 javacore 文件)。

线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。

jstack 命令格式:

jstack [option] pid

option 的可选参数:

  • -F: 当正常输出的请求不被响应时,强制输出线程堆栈。
  • -l: 除堆栈外,显示关于锁的附加信息。
  • -m: 如果调用到本地方法的话,可以显示 C/C++ 的堆栈。
PS D:\> jstack -l 5200
2020-10-08 19:03:39
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode):

"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x00000000037b8000 nid=0x3f20 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        - None
转载声明:本博客由极客挖掘机创作,采用 CC BY 3.0 CN 许可协议。可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

QR code