JVM工具 相关知识

1. JVM 常用工具

1.1. 命令行工具

基础监控工具:

  • jps :查看当前主机上的所有 JVM 进程(Java 运行程序);
  • jstat :实时监控 JVM 的内存、GC、类加载等统计信息;
  • jinfo :显示 JVM 虚拟机各项信息;
  • jcmd :一站式工具,整合了 jps、jstack、jmap 等部分功能,支持更多命令(例如:强制 GC、生成快照)。

内存分析工具:

  • jmap :生成内存快照、查看内存使用情况、查询对象实例数量等。

线程分析工具:

  • jstack :生成虚拟机当前的线程快照,用于排查死锁、线程阻塞、CPU 占用过高等问题。

1.2. 可视化工具

  • jconsole :监控内存、线程、类加载、CPU 使用率
  • jvisualvm :集成内存快照分析、线程快照、GC 监控;
  • MAT :内存泄漏分析神器,用 jmap 生成 .hprof 快照 → 导入 MAT → 查看泄漏报告。处理大快照效率高。
  • Arthas :在线诊断工具,无需重启进程,适合生产环境。

2. jps 命令

【作用】:jps(JVM Process Status ),用于查看所有 Java 进程;

【示例 1】:

jps 显示虚拟机执行主类名称以及进程的本地虚拟机唯一 ID

java 复制代码
[root@apesource-host ~]# jps
30949 jar
5148 Jps
10797 jar
16718 Bootstrap

【示例 2】:

jps -l 输出主类的全各,如果进程执行的是 Jar 包,输出 Jar 全名称

java 复制代码
[root@apesource-host ~]# jps -l
30949 web-dbpcs-materials-isolation-project-0.0.1-SNAPSHOT.jar
10797 apesource-official-website-0.0.2-SNAPSHOT.jar
16718 org.apache.catalina.startup.Bootstrap
5166 sun.tools.jps.Jps

【示例 3】:

jps -v 输出虚拟机进程启动后的 JVM 参数

java 复制代码
[root@apesource-host ~]# jps -v
30949 jar
5177 Jps -Denv.class.path=/usr/local/java/jdk1.8/lib/ -Dapplication.home=/usr/local/java/jdk1.8 -Xms8m
10797 jar
16718 Bootstrap -Djava.util.logging.config.file=/usr/local/tomcat/apache-tomcat-8.5.50/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManag er -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.w ebresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorse d.dirs= -Dcatalina.base=/usr/local/tomcat/apache-tomcat-8.5.50 -Dcatalina.home=/usr/loca l/tomcat/apache-tomcat-8.5.50 -Djava.io.tmpdir=/usr/local/tomcat/apache-tomcat-8.5.50/ temp

3. jstat 命令

【作用】:jstat(JVM Statistics Monitoring Tool )使用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程(需要远程主机提供 RMI 支持)虚拟机进程中的类信息、内存、垃圾收集、JIT 编译等运行数据,在没有 GUI,只提供了纯文本控制台环境的服务器上,它将是运行期间定位虚拟机性能问题的首选工具。

【示例 1】:

jstat -class -vmid 类加载统计

java 复制代码
[root@apesource-host ~]# jstat -class 10797
Loaded  Bytes  Unloaded  Bytes     Time   
  7142 12781.3       28    38.6       5.88

解析

  • Loaded :加载 class 的数量
  • Bytes :所占用空间大小
  • Unloaded :未加载数量
  • Bytes :未加载占用空间
  • Time :时间

【示例 2】:

jstat -gc -vmid 垃圾回收统计

java 复制代码
[root@apesource-host ~]# jstat -gc 10797
S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC      
1344.0 1344.0 109.6   0.0   11072.0   1441.9   27400.0    17493.2   40960.0 38860.7 5120.0 4725.6   2778    8.606   3      

FGCT     GCT
0.149    8.755
  • S0C :年轻代中第一个 survivor (幸存区)的容量(字节)
  • S1C :年轻代中第二个 survivor (幸存区)的容量(字节)
  • S0U :年轻代中第一个 survivor (幸存区)目前已使用空间(字节)
  • S1U :年轻代中第二个 survivor (幸存区)目前已使用空间(字节)
  • EC :年轻代中 Eden 区的容量(字节)
  • EU :年轻代中 Eden 区目前已使用空间(字节)
  • OC :老年代的容量(字节)
  • OU :老年代目前已使用空间(字节)
  • MC :metaspace (元空间) 的容量(字节)
  • MU :metaspace (元空间) 目前已使用空间(字节)
  • YGC :从应用程序启动到采样时年轻代中 GC 次数
  • YGCT :从应用程序启动到采样时年轻代中 GC 所用时间(s)
  • FGC :从应用程序启动到采样时 Full GC 的次数
  • FGCT :从应用程序启动到采样时 Full GC 所用时间(s)
  • GCT :从应用程序启动到采样时 GC 用的总时间(s)

【示例 3】:

jstat -gccapacity -vmid 堆内存统计

java 复制代码
[root@apesource-host ~]# jstat -gccapacity 10797
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
 10240.0 156992.0  13760.0 1344.0 1344.0  11072.0    20480.0   314048.0    27400.0    27400.0      0.0 1085440.0  40960.0      0.0 1048576.0   5120.0   2784     3
  • NGCMN :年轻代 (young) 中初始化 (最小) 的大小 (字节)
  • NGCMX :年轻代 (young) 的最大容量 (字节)
  • NGC :年轻代 (young) 中当前的容量 (字节)
  • S0C :年轻代中第一个 survivor (幸存区)的容量(字节)
  • S1C :年轻代中第二个 survivor (幸存区)的容量(字节)
  • EC :年轻代中 Eden 区的容量 (字节)
  • OGCMN :老年代中初始化 (最小) 的大小 (字节)
  • OGCMX :老年代的最大容量 (字节)
  • OGC :老年代当前新生成的容量 (字节)
  • OC :老年代的容量 (字节)
  • MCMN :metaspace (元空间) 中初始化 (最小) 的大小 (字节)
  • MCMX :metaspace (元空间) 的最大容量 (字节)
  • MC : metaspace (元空间) 当前新生成的容量 (字节)
  • CCSMN :最小压缩类空间大小
  • CCSMX :最大压缩类空间大小
  • CCSC :当前压缩类空间大小
  • YGC :从应用程序启动到采样时年轻代中 GC 次数
  • FGC :从应用程序启动到采样时 Full GC 次数

【示例 4】:

jstat -gcmetacapacity -vmid 元空间统计

java 复制代码
[root@apesource-host ~]# jstat -gcmetacapacity 10797
   MCMN       MCMX        MC       CCSMN      CCSMX       CCSC     YGC   FGC    FGCT     GCT   
    0.0  1085440.0    40960.0        0.0  1048576.0     5120.0  2784     3    0.149    8.772
  • MCMN :最小元数据容量
  • MCMX :最大元数据容量
  • MC :当前元数据空间大小
  • CCSMN :最小压缩类空间大小
  • CCSMX :最大压缩类空间大小
  • CCSC :当前压缩类空间大小
  • YGC :从应用程序启动到采样时年轻代中 GC 次数
  • FGC :从应用程序启动到采样时 Full GC 次数
  • FGCT :从应用程序启动到采样时 Full GC 所用时间(s)
  • GCT :从应用程序启动到采样时 GC 用的总时间(s)

【示例 5】:

jstat -gcnew -vmid 新生代统计

java 复制代码
[root@apesource-host ~]# jstat -gcnew 10797
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
1344.0 1344.0  153.0    0.0 15  15  672.0  11072.0   6567.6   2784    8.623
  • S0C :年轻代中第一个 survivor (幸存区)的容量 (字节)
  • S1C :年轻代中第二个 survivor (幸存区)的容量 (字节)
  • S0U :年轻代中第一个 survivor (幸存区)目前已使用空间 (字节)
  • S1U :年轻代中第二个 survivor (幸存区)目前已使用空间 (字节)
  • TT :持有次数限制
  • MTT :最大持有次数限制
  • DSS :期望的幸存区大小
  • EC :年轻代中 Eden 区的容量 (字节)
  • EU :年轻代中 Eden 区目前已使用空间 (字节)
  • YGC :从应用程序启动到采样时年轻代中 GC 次数
  • YGCT :从应用程序启动到采样时 Full GC 所用时间(s)

【示例 6】:

jstat -gcold -vmid 老年代统计

java 复制代码
[root@apesource-host ~]# jstat -gcold 10797
MC MU CCSC CCSU OC OU YGC FGC FGCT GC T
40960.0 38860.7 5120.0 4725.6 27400.0 17498.0 2786 3 0.149 8.776
  • MC : metaspace (元空间) 的容量 (字节)
  • MU : metaspace (元空间) 目前已使用空间 (字节)
  • CCSC :压缩类空间大小
  • CCSU :压缩类空间使用大小
  • OC : Old 代的容量 (字节)
  • OU : Old 代目前已使用空间 (字节)
  • YGC :从应用程序启动到采样时年轻代中 GC 次数
  • FGC :从应用程序启动到采样时 Full GC 的次数
  • FGCT :从应用程序启动到采样时 Full GC 所用时间(s)
  • GCT :从应用程序启动到采样时 Full GC 用的总时间(s)

【示例 7】:

jstat -gcutil -vmid 老年代统计

java 复制代码
[root@apesource-host ~]# jstat -gcutil 10797
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
30.39 0.00 56.76 63.86 94.87 92.30 2786 8.628 3 0.149 8.776
  • E :年轻代中 Eden(伊甸园)已使用的占当前容量百分比
  • O :old 代已使用的占当前容量百分比
  • M :metaspace 代已使用的占当前容量百分比
  • YGC :从应用程序启动到采样时年轻代中 GC 次数
  • YGCT :从应用程序启动到采样时年轻代中 GC 所用时间(s)
  • FGC :从应用程序启动到采样时 Full GC 的次数
  • FGCT :从应用程序启动到采样时 Full GC 所用时间(s)
  • GCT :从应用程序启动到采样时 GC 用的总时间(s)

案例:

4. jinfo 命令

【作用】:Configuration Info for Java,显示 JVM 虚拟机各项参数

【示例 1】:

jinfo vmid 输出当前 jvm 进程的全部参数和系统属性,第一部分是系统属性,第二部分是 JVM 参数。

java 复制代码
[root@apesource-host ~]# jinfo 10797
Attaching to process ID 10797, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12
Java System Properties:

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.191-b12
sun.boot.library.path = /usr/local/java/jdk1.8/jre/lib/amd64
java.protocol.handler.pkgs = org.springframework.boot.loader
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = US
user.dir = /root/project
java.vm.specification.name = Java Virtual Machine Specification
PID = 10797
java.runtime.version = 1.8.0_191-b12
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = /usr/local/java/jdk1.8/jre/lib/endorsed
line.separator =

java.io.tmpdir = /tmp
java.vm.specification.vendor = Oracle Corporation
os.name = Linux
sun.jnu.encoding = UTF-8
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
spring.beaninfo.ignore = true
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 3.10.0-514.26.2.el7.x86_64
LOG_FILE = /root/project/offical-website.log
user.home = /root
user.timezone = Asia/Shanghai
catalina.useNaming = false
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
catalina.home = /tmp/tomcat.8244287809132104734.80
user.name = root
java.class.path = apesource-official-website-0.0.2-SNAPSHOT.jar
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = apesource-official-website-0.0.2-SNAPSHOT.jar
java.home = /usr/local/java/jdk1.8/jre
user.language = en
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.X11.XToolkit
java.vm.info = mixed mode
java.version = 1.8.0_191
java.ext.dirs = /usr/local/java/jdk1.8/jre/lib/ext:/usr/java/packages/lib/ext
sun.boot.class.path = /usr/local/java/jdk1.8/jre/lib/resources.jar:/usr/local/java/jdk1.8/jre/lib/rt.jar:/usr/local/java/jdk1.8/jre/lib/sunrsasign.jar:/usr/local/java/jdk1.8/jre/lib/jsse.jar:/usr/local/java/jdk1.8/jre/lib/jce.jar:/usr/local/java/jdk1.8/jre/lib/charsets.jar:/usr/local/java/jdk1.8/jre/lib/jfr.jar:/usr/local/java/jdk1.8/jre/classes
java.awt.headless = true
java.vendor = Oracle Corporation
catalina.base = /tmp/tomcat.8244287809132104734.80
file.separator = /
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.cpu.isalist =

VM Flags:
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=10485760 -XX:OldSize=20971520 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops

【示例 2】:

jinfo -flags vmid 输出全部 JVM 参数

java 复制代码
[root@apesource-host ~]# jinfo -flags 10797
Attaching to process ID 10797, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=10485760 -XX:OldSize=20971520 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops

【示例 3】:

jinfo -flag InitialHeapSize vmid 查看堆的初始容量

java 复制代码
[root@apesource-host ~]# jinfo -flag InitialHeapSize 10797
-XX:InitialHeapSize=31457280

【示例 4】:

jinfo -flag PrintGC vmid 查看是否开启 GC 日志,如果没有打开,则输出: -XX:-PrintGC。使用 +PrintGC 开启

java 复制代码
[root@apesource-host ~]# jinfo -flag PrintGC 10797
-XX:-PrintGC
[root@apesource-host ~]# jinfo -flag +PrintGC 10797
[root@apesource-host ~]# jinfo -flag PrintGC 10797
-XX:+PrintGC

5. jstack 命令

【作用】:Stack Trace for Java,用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合信息。生成线程快照的目的主要是定位线程长时间出现停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的原因。线程出现停顿的时候通过 jstack 来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者在等待些什么资源。

【线程死锁案例】:

java 复制代码
public class DeadLockDemo {
	private static Object objLock1 = new Object();	// 对象锁1
    private static Object objLock2 = new Object();	// 对象锁2

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (objLock1) {
                System.out.println(Thread.currentThread().getName() + "获取对象锁1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                System.out.println(Thread.currentThread().getName() + "等待获取对象锁2");
                synchronized (objLock2) {
                    System.out.println(Thread.currentThread().getName() + "获取对象锁2");
                }
            }
        }, "线程 1").start();

        new Thread(() -> {
            synchronized (objLock2) {
                System.out.println(Thread.currentThread().getName() + "获取对象锁2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                System.out.println(Thread.currentThread().getName() + "等待获取对象锁1");
                synchronized (objLock1) {
                    System.out.println(Thread.currentThread().getName() + "获取对象锁1");
                }
            }
        }, "线程 2").start();
    }
}

输出 :出现死锁

线程 1 通过 synchronized (objLock1) 获得 objLock1 的监视器锁,然后通过 Thread.sleep (1000); 让线程 1 休眠 1s,目的是让线程 B 得到执行然后获取到 objLock2 的监视器锁,线程 1 和线程 2 休眠结束了都开始企图请求获取对方的对象锁,然后这两个线程就会陷入互相等待的状态,这也就产生了死锁。

输出案例:

【实时分析】:jstack vmid 用于生成虚拟机当前时刻的线程快照。

java 复制代码
C:\Users\apple>jstack 4984

输出:

java 复制代码
Found one Java-level deadlock:
=============================
"线程 2":
  waiting to lock monitor 0x000000001c263628 (object 0x000000076ba263c8, a java.lang.Object),
  which is held by "线程 1"
"线程 1":
  waiting to lock monitor 0x000000001c260c38 (object 0x000000076ba263d8, a java.lang.Object),
  which is held by "线程 2"

Java stack information for the threads listed above:
===================================================
"线程 2":
        at com.apesource.demo.DeadLockDemo.lambda$1(DeadLockDemo.java:33)
        - waiting to lock <0x000000076ba263c8> (a java.lang.Object)
        - locked <0x000000076ba263d8> (a java.lang.Object)
        at com.apesource.demo.DeadLockDemo$$Lambda$2/13326370.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
"线程 1":
        at com.apesource.demo.DeadLockDemo.lambda$0(DeadLockDemo.java:18)
        - waiting to lock <0x000000076ba263d8> (a java.lang.Object)
        - locked <0x000000076ba263c8> (a java.lang.Object)
        at com.apesource.demo.DeadLockDemo$$Lambda$1/201556483.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

Found 1 deadlock.

6. jconsole

7. jvisualvm

8. Arthas

Arthas 是阿里巴巴开源的 Java 在线诊断工具,可在不修改代码、不重启服务的情况下,实时监控和诊断生产环境中的 Java 应用。

・【启动 Arthas】

java 复制代码
java -jar arthas -boot.jar

・【dashboard】实时展示 JVM 核心指标(线程、内存、GC、CPU、类加载)。

  • 线程:状态(RUNNABLE / BLOCKED )、CPU 占比(可快速发现 "高 CPU 线程" )。
  • 内存:各区域(堆 / 非堆)的使用率(判断是否内存泄漏或溢出)。
  • GC:各收集器的回收次数、耗时(判断 GC 是否频繁)。
java 复制代码
dashboard

会在进程中插入阿尔萨斯的栈帧:

・【thread】查看线程状态,定位 CPU 占用过高的线程和死锁。

java 复制代码
thread #列出所有线程的简要信息(ID、状态、CPU 占比)
thread 线程 ID #查看指定线程的完整调用栈
thread -n 3 #显示 CPU 占比最高的前 3 个线程(快速定位 "CPU 飙升" 问题)
thread -b #检测是否有线程阻塞(找到 "持有锁" 和 "等待锁" 的线程,检查死锁)

显示 CPU 占比最高的前 3 个线程:

・【jvm】查看 JVM 参数、内存模型、GC 配置等静态信息。

  • 内存:堆大小(初始 / 最大)、各个分代(Eden / Survivor / Old )配置。
  • GC:使用的收集器(如 G1 、CMS )、回收策略参数。
  • 系统:启动时间、操作系统信息。
java 复制代码
jvm
相关推荐
别看我只是一直狼2 小时前
【保姆级教程】2025年最新版!从零到一搭建 Spring Boot 项目,后端小白也能轻松上手!
java·spring boot
渣哥2 小时前
从字节码到对象头:synchronized 如何实现?
java
怪兽20142 小时前
JRE、JDK、JVM 及 JIT 之间有什么不同?
java·面试
翻斗花园刘大胆2 小时前
JavaWeb之HttpServletRequest与HttpServletResponse详解及快递管理系统实践
java·开发语言·数据库·mysql·servlet·架构·mvc
vker2 小时前
第 4 天:建造者模式(Builder Pattern)—— 创建型模式
java·后端·设计模式
Coding_Doggy3 小时前
java面试day3 | 框架篇、Spring、SpringMVC、SpringBoot、MyBatis、注解、AOP、Bean
java·mysql·面试
Li zlun3 小时前
Kubernetes 进阶实战:CRD、Gateway API 与优先级调度
java·kubernetes·gateway
七夜zippoe3 小时前
Java 生态监控体系实战:Prometheus+Grafana+SkyWalking 整合全指南(二)
java·grafana·prometheus
没事学AI3 小时前
Caffeine三种缓存过期策略总结:原理、实战与调优
java·缓存·caffeine·缓存穿透防护·caffeine缓存