JVM-虚拟机故障处理工具

JVM-虚拟机故障处理工具

一、故障处理命令

1.1 jps

可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(LVMID,Local Virtual Machine Identifier)。

java 复制代码
//用于显示java中当前正在运行的线程
C:\Users\admin>jps -help
usage: jps [-help]
    jps [-q] [-mlvV] [<hostid>]
​
Definitions:
 <hostid>:      <hostname>[:<port>]
​
// 1. 不带参数
C:\Users\admin>jps
5600 Launcher
9808 Launcher
7812 Jps
4104
5308 RemoteMavenServer
    
![image-20230116101850567.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0b70ec822d62496ca761c51429290683~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=360&h=168&s=12943&e=png&b=f5ebe4)
// 2. 常用jps -l 输出主类的全名,如果进程执行的是 JAR 包,则输出JAR 路径
C:\Users\admin>jps -l
5600 org.jetbrains.jps.cmdline.Launcher
9808 org.jetbrains.jps.cmdline.Launcher
4104
2332 sun.tools.jps.Jps
5308 org.jetbrains.idea.maven.server.RemoteMavenServer
​
// 3. 输出虚拟机进程启动时的JVM参数
C:\Users\admin> jps -v
19724 RemoteJdbcServer -Djava.rmi.server.hostname=127.0.0.1 -Duser.timezone=UTC -Xmx2033m -Xms128m -Dfile.encoding=UTF-8
4924  RemoteMavenServer36 -Djava.awt.headless=true -Dmaven.defaultProjectBuilder.disableGlobalModelCache=true -Didea.version=2021.1.3 -Didea.maven.embedder.version=3.8.1 -Xmx768m -Dfile.encoding=GBK

1.2 jstat

jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类加载、内存、垃圾收集、即时编译等运行时数据,在没有GUI图形界面、只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的常用工具。

java 复制代码
C:\WINDOWS\system32> jps -l
6048 jvm.part7.TestTool
​
// 1. 没有后面测时间间隔,和查询次数,则只查询一次
C:\WINDOWS\system32> jstat -gc 6048
S0C    S1C     S0U  S1U  EC       EU        OC        OU     MC     MU     CCSC   CCSU  YGC  YGCT   FGC  FGCT   GCT
512.0  512.0   0.0  0.0  310272.0 117903.3  175104.0  689.1  4864.0 3079.6 512.0  323.6 379  0.258  0    0.000  0.258
​
// 2. 查看进程6408运行时数据情况,每1s查看一次,查询10次
C:\WINDOWS\system32> jstat -gc 6408 1000 10
S0C    S1C    S0U  S1U  EC        EU        OC        OU    MC     MU     CCSC   CCSU   YGC  YGCT  FGC FGCT  GCT
512.0  512.0  0.0  0.0  252928.0  0.0       175104.0  689.1 4864.0 3079.6 512.0  323.6  599  0.366 0   0.000 0.366
512.0  512.0  0.0  0.0  454656.0  9093.1    175104.0  689.1 4864.0 3079.6 512.0  323.6  617  0.376 0   0.000 0.376
512.0  512.0  0.0  0.0  278528.0  0.0       175104.0  689.1 4864.0 3079.6 512.0  323.6  634  0.384 0   0.000 0.384
512.0  512.0  0.0  0.0  516096.0  196116.2  175104.0  689.1 4864.0 3079.6 512.0  323.6  652  0.393 0   0.000 0.393
512.0  512.0  0.0  0.0  325632.0  71639.0   175104.0  689.1 4864.0 3079.6 512.0  323.6  668  0.401 0   0.000 0.401
512.0  512.0  0.0  0.0  523776.0  125705.9  175104.0  689.1 4864.0 3079.6 512.0  323.6  690  0.410 0   0.000 0.410
512.0  512.0  0.0  0.0  274432.0  0.0       175104.0  689.1 4864.0 3079.6 512.0  323.6  705  0.417 0   0.000 0.417
512.0  512.0  0.0  0.0  414720.0  0.0       175104.0  689.1 4864.0 3079.6 512.0  323.6  728  0.428 0   0.000 0.428
512.0  512.0  0.0  0.0  411648.0  8233.0    175104.0  689.1 4864.0 3079.6 512.0  323.6  744  0.436 0   0.000 0.436
512.0  512.0  0.0  0.0  440832.0  229232.5  175104.0  689.1 4864.0 3079.6 512.0  323.6  758  0.443 0   0.000 0.443
    
// SOC:Survivor0剩余空间 , S1C:Survivor1剩余空间 , S0U:Survivor0使用大小 , S1U:Survivor1使用大小 
// EC:Eden剩余空间 ,  EU:使用大小 
// OC:老年代剩余空间 , OU:老年代使用大小
// MC:元空间剩余空间 , MU:元空间使用大小
// CCSC: 当前压缩类空间CCS(即:Klass Metaspace)的大小 , CCSU:压缩类空间使用大小 
// YGC:发生Young GC次数 , YGCT:发生Young GC总耗时
// FGC:发生Full GC次数 , FGCT:发生Full GCT总耗时
// GCT:发生GC总耗时

1.3 jcmd

jcmd 从JDK1.7开始增加的命令。

jcmd 是一个多功能的工具,相比 jstat 功能更为全面的工具,可用于获取目标 Java 进程的性能统计、JFR、内存使用、垃圾收集、线程堆栈、JVM 运行时间,也可以手动执行GC、导出线程信息、堆信息等信息。

  • 1、jcmd pid help 列出当前运行Java进程可以执行的操作

    shell 复制代码
    C:\WINDOWS\system32> jcmd 21892 help
    21892:
    The following commands are available:
    JFR.stop
    JFR.start
    JFR.dump
    JFR.check
    VM.native_memory
    VM.check_commercial_features
    VM.unlock_commercial_features
    ManagementAgent.stop
    ManagementAgent.start_local
    ManagementAgent.start
    VM.classloader_stats
    GC.rotate_log
    Thread.print
    GC.class_stats
    GC.class_histogram
    GC.heap_dump
    GC.finalizer_info
    GC.heap_info
    GC.run_finalization
    GC.run
    VM.uptime
    VM.dynlibs
    VM.flags
    VM.system_properties
    VM.command_line
    VM.version
    help
  • 2、查看当前所有进程

    shell 复制代码
    C:\WINDOWS\system32> jcmd -l
    14560
    18548 sun.tools.jcmd.JCmd -l
    21892 jvm.part7.TestTool
    19724 com.intellij.database.remote.RemoteJdbcServer com.mysql.cj.jdbc.Driver
    4924 org.jetbrains.idea.maven.server.RemoteMavenServer36
  • 3、查看某一个进程的JVM参数

    shell 复制代码
    C:\WINDOWS\system32> jcmd -l
    14560
    18548 sun.tools.jcmd.JCmd -l
    21892 jvm.part7.TestTool
    19724 com.intellij.database.remote.RemoteJdbcServer com.mysql.cj.jdbc.Driver
    4924 org.jetbrains.idea.maven.server.RemoteMavenServer36
  • 4、查看某一个进程的JVM参数

    shell 复制代码
            C:\WINDOWS\system32> jcmd 21892 VM.flags
            21892:-XX:CICompilerCount=4 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4265607168 -XX:MaxNewSize=1421869056 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=89128960 -XX:OldSize=179306496 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
  • 5、查看JVM的启动时长

    makefile 复制代码
    C:\WINDOWS\system32> jcmd 21892 VM.uptime
    21892:
    644.984 s
  • 6、jcmd pid GC.class_histogram :查看系统中类的统计信息

    yaml 复制代码
    C:\WINDOWS\system32> jcmd 21892 GC.class_histogram
    21892:
    ​
     num     #instances         #bytes  class name
    ----------------------------------------------
       1:          4706         458208  [C
       2:           472         155176  [B
       3:          4557         109368  java.lang.String
       4:           706          80880  java.lang.Class
       5:           645          42680  [Ljava.lang.Object;
       6:           791          31640  java.util.TreeMap$Entry
       7:           654          26160  java.util.LinkedHashMap$Entry
       8:           427          19008  [Ljava.lang.String;
       9:           416          13312  java.util.HashMap$Node
  • 7、jcmd pid Thread.print :查看线程的堆栈信息

    php 复制代码
    C:\WINDOWS\system32> jcmd 23788 Thread.print
    23788:
    2023-01-16 14:38:40
    Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.291-b10 mixed mode):
    
    "DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x0000027c141a3000 nid=0x5e68 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Thread-B" #15 prio=5 os_prio=0 tid=0x0000027c31980800 nid=0x2f98 waiting for monitor entry [0x000000be44dfe000]
       java.lang.Thread.State: BLOCKED (on object monitor)
            at jvm.A.method(DeadLock.java:17)
            - waiting to lock <0x000000076bbba688> (a java.lang.Class for jvm.A)
            at jvm.B.method(DeadLock.java:33)
            - locked <0x000000076be49dd8> (a java.lang.Class for jvm.B)
            at jvm.DeadLock.lambda$main$1(DeadLock.java:9)
            at jvm.DeadLock$$Lambda$2/706277948.run(Unknown Source)
            at java.lang.Thread.run(Thread.java:748)
    
    "Thread-A" #14 prio=5 os_prio=0 tid=0x0000027c3197d800 nid=0x18a0 waiting for monitor entry [0x000000be44cff000]
       java.lang.Thread.State: BLOCKED (on object monitor)
            at jvm.B.method(DeadLock.java:29)
            - waiting to lock <0x000000076be49dd8> (a java.lang.Class for jvm.B)
            at jvm.A.method(DeadLock.java:21)
            - locked <0x000000076bbba688> (a java.lang.Class for jvm.A)
            at jvm.DeadLock.lambda$main$0(DeadLock.java:8)
            at jvm.DeadLock$$Lambda$1/1688019098.run(Unknown Source)
            at java.lang.Thread.run(Thread.java:748)
    
    "Service Thread" #13 daemon prio=9 os_prio=0 tid=0x0000027c3160c800 nid=0x3044 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
  • 8、jcmd pid GC.heap_dump :导出Heap dump 文件,导出的文件可以通过jvisualvm查看

    javascript 复制代码
    // 导出Heap dump 文件
    C:\WINDOWS\system32> jcmd 23788 GC.heap_dump C:\Users\admin\Desktop\heap\javaheap
    23788:
    Heap dump file created
    
    // 导出的文件可以通过jvisualvm查看
    PS C:\WINDOWS\system32> jvisualvm
    The launcher has determined that the parent process has a console and will reuse it for its own console output.
    Closing the console will result in termination of the running program.
    Use '--console suppress' to suppress console output.
    Use '--console new' to create a separate console window.

    打开Visualvm ,装入上面dump出的文件,注意:文件类型要选择堆 Dump

    查看文件的一些基本信息:

1.4 jinfo

jinfo(Configuration Info for Java)的作用是实时查看和调整虚拟机各项参数。

ini 复制代码
// 查看进程4332年轻代Survivor空间占比
C:\WINDOWS\system32> jinfo -flag SurvivorRatio 4332
-XX:SurvivorRatio=8

1.5 jmap

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

ini 复制代码
C:\WINDOWS\system32> jmap -dump:file=C:\heapdump.bin 24600
Dumping heap to C:\heapdump.bin ...
Heap dump file created

然后利用 Java堆内存工具:VisualVM,JProfiler,YourKit Java Profiler等工具查看dump出的文件。

下图是我用 JProfiler打开的 heapdump.bin 的结果:

1.6 jhat

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

erlang 复制代码
// 这里还是分析上面dump出的文件
C:\WINDOWS\system32> jhat C:\Users\admin\Desktop\heap\javaheap
Reading from C:\Users\admin\Desktop\heap\javaheap...
Dump file created Mon Jan 16 14:43:47 CST 2023
Snapshot read, resolving...
Resolving 14726 objects...
Chasing references, expect 2 dots..
Eliminating duplicate references..
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

打开地址:http://localhost:7000/;下面的点开分析就行。

1.7 jstack

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如:线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。

php 复制代码
C:\WINDOWS\system32> jstack 23788
2023-01-16 15:13:46
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.291-b10 mixed mode):
​
"DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x0000027c141a3000 nid=0x5e68 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
​
"Thread-B" #15 prio=5 os_prio=0 tid=0x0000027c31980800 nid=0x2f98 waiting for monitor entry [0x000000be44dfe000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at jvm.A.method(DeadLock.java:17)
        - waiting to lock <0x00000006c1c01508> (a java.lang.Class for jvm.A)
        at jvm.B.method(DeadLock.java:33)
        - locked <0x00000006c1c01570> (a java.lang.Class for jvm.B)
        at jvm.DeadLock.lambda$main$1(DeadLock.java:9)
        at jvm.DeadLock$$Lambda$2/706277948.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
​
"Thread-A" #14 prio=5 os_prio=0 tid=0x0000027c3197d800 nid=0x18a0 waiting for monitor entry [0x000000be44cff000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at jvm.B.method(DeadLock.java:29)
        - waiting to lock <0x00000006c1c01570> (a java.lang.Class for jvm.B)
        at jvm.A.method(DeadLock.java:21)
        - locked <0x00000006c1c01508> (a java.lang.Class for jvm.A)
        at jvm.DeadLock.lambda$main$0(DeadLock.java:8)
        at jvm.DeadLock$$Lambda$1/1688019098.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
​
"Service Thread" #13 daemon prio=9 os_prio=0 tid=0x0000027c3160c800 nid=0x3044 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

二、可视化故障处理工具

两款可视化工具,用到的死锁案例:

java 复制代码
public class DeadLock {
    public static void main(String[] args) {
        //当A线程执行方法A.method的时候,会去执行B.method();
        //这个时候,A尝试去获取B的锁,但是B的锁已经被B线程获取,此时A线程就会等待B线程释放B锁
        //B线程与之相反,最终造成死锁。
        new Thread(()->A.method(),"Thread-A").start();
        new Thread(()->B.method(),"Thread-B").start();
    }
}
class A {
    //当synchronized被static修饰的时候,synchronized所持有的锁不是当前类的锁
    //而是当前类A所对应的class对象所对应的锁,
    //那么,这样使得不论A有多少个实例、对象,它们所拥有的都是同一把锁,都是类A所对应的class对象所拥有的锁
    public static synchronized void method(){
        System.out.println("method from A");

        try {
            Thread.sleep(3000);
            B.method();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class B {
    public static synchronized void method(){
        System.out.println("method from B");

        try {
            Thread.sleep(3000);
            A.method();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2.1 JConsole

JConsole(Java Monitoring and Management Console)是一款基于JMX(Java Manage-mentExtensions)的可视化监视、管理工具。

查看内存使用情况,下面的图标选项,我们看到,对内存的模型划分,像:老年代,Survivor,Eden,元空间这些都可以查看其使用情况:

线程信息查看:这里可以检测死锁的存在!

可以看到:两个线程Thread-AThread-B 相互拥有各自的资源,都不释放,造成BLOCKED

2.2 VisualVM

Windows下打开VisualVM:

javascript 复制代码
PS C:\WINDOWS\system32> jvisualvm
The launcher has determined that the parent process has a console and will reuse it for its own console output.
Closing the console will result in termination of the running program.
Use '--console suppress' to suppress console output.
Use '--console new' to create a separate console window.

可以监控:CPU,堆,元空间,类,线程信息,可以主动执行垃圾回收,可以dump出堆信息:

查看线程信息:可以查看当前进程下的所有线程信息,还可以检查到死锁,可以dump出线程信息:

更多功能进入界面慢慢研究。

相关推荐
hakesashou1 分钟前
Python中常用的函数介绍
java·网络·python
佚先森10 分钟前
2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程
java·html
古月居GYH23 分钟前
在C++上实现反射用法
java·开发语言·c++
请你打开电视看看1 小时前
Jvm知识点
jvm
儿时可乖了1 小时前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
ruleslol1 小时前
java基础概念37:正则表达式2-爬虫
java
xmh-sxh-13141 小时前
jdk各个版本介绍
java
天天扭码2 小时前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构