橘子学JVM之命令行监控03之jinfo

本文介绍jinfo工具的基本使用方法,包括如何查看和修改JVM配置参数。通过具体示例展示了如何利用jinfo查看系统属性、非默认JVM参数以及如何动态设置参数。

一、简介

jinfo:实时查看和修改JVM配置参数
jinfo(Configuration Info for Java):查看虚拟机配置参数信息,也可用于调整虚拟机的配置参数。在很多情况卡,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值。在这种情况下,可能需要通过查找文档获取某个参数的默认值。这个查找过程可能是非常艰难的。但有了jinfo工具,开发人员可以很方便地找到Java虚拟机参数的当前值。就是说我们那些自己设置的参数我们能通过jps -v是能看到值的,要是那些默认的我们jps -v就看不到了,所以此时需要jinfo.

基本使用语法为:jinfo [options] pid
说明:java 进程ID必须要加上
在这里插入图片描述

二、jinfo用于查看参数

先启动一个程序,用于测试,我们开之前那个程序,就是一个休眠,用于观察的。而且设置堆空间的大小是32m,然后启动程序,观察jps的进程id是109848

/**
 * @author: levi
 * @description: -Xms32m -Xmx32m
 * @date: 2022-10-1 20:07
 * @version: 1.0
 */
public class TestJps {
    public static void main(String[] args) {
        try {
            Thread.sleep(10000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1、 jinfo -sysprops

测试一下 jinfo -sysprops 109848得到结果为:

Attaching to process ID 109848, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.181-b13
sun.boot.library.path = D:\env\java\jdk\jre\bin
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 =
sun.java.launcher = SUN_STANDARD
user.script =
user.country = CN
user.dir = D:\work\workspace\jvm\heima
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_181-b13
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
os.arch = amd64
java.endorsed.dirs = D:\env\java\jdk\jre\lib\endorsed
line.separator =

java.io.tmpdir = C:\Users\YX\AppData\Local\Temp\
java.vm.specification.vendor = Oracle Corporation
user.variant =
os.name = Windows 10
sun.jnu.encoding = GBK
java.library.path = D:\env\java\jdk\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;D:\env\java\jdk\bin;D:\env\java\jdk\jre\bin;C:\Program Files (x86)\Common Files\NetSarang;D:\Program Files\xshell\;D:\Program Files\netcat-win32-1.12;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\iCLS\;C:\Program Files\Intel\Intel(R) Management Engine Components\iCLS\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;D:\Program Files\Git\cmd;C:\Program Files (x86)\MySQL\MySQL Fabric 1.5 & MySQL Utilities 1.5\;C:\Program Files (x86)\MySQL\MySQL Fabric 1.5 & MySQL Utilities 1.5\Doctrine extensions for PHP\;D:\Program Files\nodejs;D:\work\software\gradle\gradle-4.10.3-bin\gradle-4.10.3\bin;C:\Users\YX\AppData\Local\Microsoft\WindowsApps;C:\Users\YX\AppData\Local\Programs\Microsoft VS Code\bin;C:\Users\yx\AppData\Roaming\npm;.
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 10.0
user.home = C:\Users\YX
user.timezone = Asia/Shanghai
java.awt.printerjob = sun.awt.windows.WPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
user.name = YX
java.class.path = D:\env\java\jdk\jre\lib\charsets.jar;D:\env\java\jdk\jre\lib\deploy.jar;D:\env\java\jdk\jre\lib\ext\access-bridge-64.jar;D:\env\java\jdk\jre\lib\ext\cldrdata.jar;D:\env\java\jdk\jre\lib\ext\dnsns.jar;D:\env\java\jdk\jre\lib\ext\jaccess.jar;D:\env\java\jdk\jre\lib\ext\jfxrt.jar;D:\env\java\jdk\jre\lib\ext\localedata.jar;D:\env\java\jdk\jre\lib\ext\nashorn.jar;D:\env\java\jdk\jre\lib\ext\sunec.jar;D:\env\java\jdk\jre\lib\ext\sunjce_provider.jar;D:\env\java\jdk\jre\lib\ext\sunmscapi.jar;D:\env\java\jdk\jre\lib\ext\sunpkcs11.jar;D:\env\java\jdk\jre\lib\ext\zipfs.jar;D:\env\java\jdk\jre\lib\javaws.jar;D:\env\java\jdk\jre\lib\jce.jar;D:\env\java\jdk\jre\lib\jfr.jar;D:\env\java\jdk\jre\lib\jfxswt.jar;D:\env\java\jdk\jre\lib\jsse.jar;D:\env\java\jdk\jre\lib\management-agent.jar;D:\env\java\jdk\jre\lib\plugin.jar;D:\env\java\jdk\jre\lib\resources.jar;D:\env\java\jdk\jre\lib\rt.jar;D:\work\workspace\jvm\heima\target\classes;D:\work\software\maven\apache-maven-3.6.1\maven-repo\com\fasterxml\jackson\core\jackson-databind\2.13.0\jackson-databind-2.13.0.jar;D:\work\software\maven\apache-maven-3.6.1\maven-repo\com\fasterxml\jackson\core\jackson-core\2.13.0\jackson-core-2.13.0.jar;D:\work\software\maven\apache-maven-3.6.1\maven-repo\com\fasterxml\jackson\core\jackson-annotations\2.13.0\jackson-annotations-2.13.0.jar;D:\work\software\maven\apache-maven-3.6.1\maven-repo\org\apache\directory\studio\org.apache.commons.io\2.4\org.apache.commons.io-2.4.jar;D:\work\software\maven\apache-maven-3.6.1\maven-repo\commons-io\commons-io\2.4\commons-io-2.4.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar
java.vm.specification.version = 1.8
sun.arch.data.model = 64
sun.java.command = com.lyx.cmd.TestJps hello world
java.home = D:\env\java\jdk\jre
user.language = zh
java.specification.vendor = Oracle Corporation
awt.toolkit = sun.awt.windows.WToolkit
java.vm.info = mixed mode
java.version = 1.8.0_181
java.ext.dirs = D:\env\java\jdk\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
sun.boot.class.path = D:\env\java\jdk\jre\lib\resources.jar;D:\env\java\jdk\jre\lib\rt.jar;D:\env\java\jdk\jre\lib\sunrsasign.jar;D:\env\java\jdk\jre\lib\jsse.jar;D:\env\java\jdk\jre\lib\jce.jar;D:\env\java\jdk\jre\lib\charsets.jar;D:\env\java\jdk\jre\lib\jfr.jar;D:\env\java\jdk\jre\classes
java.vendor = Oracle Corporation
file.separator = \
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.io.unicode.encoding = UnicodeLittle
sun.cpu.endian = little
sun.desktop = windows
sun.cpu.isalist = amd64

我们看到输出了所有的系统的信息配置,你也可以用代码System.getproperties来获取。啥都有,太全了也没啥意思。

2、jinfo -flags

执行jinfo -flags 109848查看结果为

Attaching to process ID 109848, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.181-b13
# 这部分是非默认的参数,也就是不是默认的包括我们自己设置的和系统为我们设置的一些,你像我们设置了堆空间大小是32m,-XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432就是这个,其余的像使用什么压缩指针开启,之类的,使用ParallelGC回收器是系统为我们设置的。
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=33554432 -XX:MaxHeapSize=33554432 -XX:MaxNewSize=11010048 -XX:MinHeapDeltaBytes=524288        -XX:NewSize=11010048 -XX:OldSize=22544384 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIn       dividualAllocation -XX:+UseParallelGC

# 这部分是你命令行里面设置的,也就是我们启动的时候设置的堆空间为32m
Command line:  -Xms32m -Xmx32m -javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar=57790:D:\Program Files\JetBrains\IntelliJ ID       EA 2020.1\bin -Dfile.encoding=UTF-8

3、jinfo -flag

上面我们用flags是把所有的都输出了,假如我们就想看某一个参数的设置的值,那我们就要用jinfo -flag不带s了,就单独看一个。
假如我们想看一下是不是使用了UseParallelGC这个回收器,那我们就使用:
jinfo -flag UseParallelGC 109848即可。

D:\>jinfo  -flag   UseParallelGC   109848
-XX:+UseParallelGC  这是输出结果,我们看到是+意思是开启的。

我们查看一下g1垃圾器,是啥结果。
D:\>jinfo  -flag   UseG1GC   109848
-XX:-UseG1GC  我们看到是-是关闭的意思,因为我是1.8的jdk,所以g1是关闭的。你要是用jdk9及以后就是开启的了。

我们查看一下堆空间最大大小
D:\>jinfo  -flag   MaxHeapSize   109848
-XX:MaxHeapSize=33554432 就是我们设置的32m

三、jinfo用于设置参数

注意我们这个设置是立即生效的,但是也不是都能设置立即生效,只有一种情况可以。并非所有的参数都支持动态修改,参数只有被标记为manageable的flag可以实时的被修改,所以这个修改能力其实是有限的。
可以通过这个命令去查看哪些参数有这个标志:
java -XX:+PrintFlagsFinal -version | grep manageable
在这里插入图片描述
设置参数的操作命令就是:jinfo -flag [±]name 进程id

设置一下PrintGCDetails这个

我们先查看一下这个参数是不是开启了,
在这里插入图片描述
此时我们使用jinfo去修改设置这个参数:jinfo -flag +PrintGCDetails 109848,使用减号还能关闭
在这里插入图片描述
这种开关类型你通过±就能设置,那种数值类型的直接后面HeapDumpPath=100这样子就行了。
ps:我们上面那操作都是指定的进程id的,就是只针对这个进程的,要是你的程序挂了或者重启了,这时候进程号变了,那你之前的修改就作废了,重新开始。

四、拓展

java -XX:+PrintFlagsInitial 查看所有JVM参数启动的初始值
也就是那种jvm默认的参数。

[Global flags]
    intx ActiveProcessorCount                      = -1                                  {product}
    uintx AdaptiveSizeDecrementScaleFactor          = 4                                   {product}
    uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
    uintx AdaptiveSizePausePolicy                   = 0                                   {product}
...

java -XX:+PrintFlagsFinal 查看所有JVM参数的最终值,就是启动的时候你可能指定了一些值,或者jvm给你设置了一些值,这种就是最终值,也就是这个命令看到的。这种 := 就是被修改过的。

[Global flags]
    intx ActiveProcessorCount                      = -1                                  {product}
...
    intx CICompilerCount                          := 4                                   {product}
    uintx InitialHeapSize                          := 333447168                           {product}
    uintx MaxHeapSize                              := 1029701632                          {product}
    uintx MaxNewSize                               := 1774714880                          {product}

java -XX:+PrintCommandLineFlags 查看哪些已经被用户或者JVM设置过的详细的XX参数的名称和值,这个就是你在命令行处理过的,就是启动的时候你设置的jvm参数,单独在这里显示一下,比较直接,上面那种显示的比较多。

-XX:InitialHeapSize=332790016 -XX:MaxHeapSize=5324640256 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
<think>好的,用户现在想了解如何通过命令行监控JVM。首先,我需要回忆一下JVM自带的监控工具,比如jps、jstat、jstack、jmap这些命令。这些都是JDK自带的工具,属于jdk/bin目录下的可执行文件,用户可能已经安装了JDK,所以不需要额外安装。 接下来,用户可能是开发人员或者运维人员,遇到了性能问题,比如应用卡顿、内存泄漏,或者高CPU使用率,想要快速诊断问题。他们可能需要实时监控JVM的状态,或者生成堆转储文件来分析内存使用情况。 用户可能对JVM监控不太熟悉,所以需要分步骤介绍每个命令的用途和常用参数。比如jps用来查看Java进程的PID,这是其他命令的基础。然后jstat可以查看类加载、内存、GC情况,适合实时监控。jstack用来抓取线程快照,分析线程死锁或高CPU问题。jmap用于内存分析,生成堆转储文件,结合MAT或VisualVM分析。 另外,用户可能不知道如何组合使用这些命令,或者在不同场景下应该使用哪个工具。比如,当应用响应变慢时,先用jps找到PID,再用jstat看看GC是否频繁,内存是否有泄漏迹象,然后用jstack检查是否有线程阻塞。如果怀疑内存泄漏,可以用jmap生成堆转储进一步分析。 还需要考虑用户的操作系统,这些命令在Linux和Windows下是否适用,但一般来说,命令行工具是跨平台的,可能路径或命令格式稍有不同,但基本用法一致。另外,用户可能需要知道如何安装或确认JDK是否正确安装,因为有些环境可能只安装了JRE,而没有这些工具。 另外,用户可能对命令行参数不太熟悉,需要给出具体的例子,比如jstat -gcutil PID 1000 10,这样他们可以直接复制使用。还要提醒权限问题,比如需要足够的权限执行这些命令,否则可能会失败。 还有,高级工具如jcmd和jvisualvm可能也是用户需要的,但用户明确要求的是命令行监控,所以jvisualvm虽然是图形化工具,但可以简单提及作为补充。jcmd是一个综合性的工具,可以替代多个命令,适合更复杂的诊断需求。 用户可能希望有一个总结性的步骤指南,比如当出现问题时,第一步做什么,第二步做什么,这样他们可以按图索骥。需要强调生成堆转储可能会暂停应用,所以要在适当的时候执行,避免影响线上服务。 最后,要检查是否有遗漏的工具或常见问题,比如如何分析堆转储文件,可能需要推荐其他工具如Eclipse MAT,但用户的问题仅限于命令行监控,所以这部分可能不需要展开。总之,要确保回答全面,步骤清晰,示例明确,便于用户实际操作。</think>以下是关于 **JVM 命令行监控工具**的详细介绍,涵盖常用工具、核心命令及典型使用场景,帮助快速定位 JVM 性能问题: --- ### **1. 基础工具概览** JVM 自带命令行工具(位于 `JDK/bin` 目录),无需额外安装,可直接监控运行中的 Java 进程: | 工具 | 用途 | 核心功能 | |-----------|------------------------------|-----------------------------| | `jps` | 查看 Java 进程列表 | 快速获取进程 PID | | `jstat` | 实时监控 JVM 统计信息 | 类加载、内存、GC、JIT 等 | | `jstack` | 生成线程快照(Thread Dump) | 分析线程死锁、阻塞 | | `jmap` | 生成堆转储(Heap Dump) | 内存泄漏分析 | | `jinfo` | 查看/修改 JVM 参数 | 动态调整运行时配置 | | `jcmd` | 综合诊断工具(JDK 7+) | 执行多种诊断命令 | --- ### **2. 核心工具详解** #### **(1) `jps`:快速定位 Java 进程** ```bash jps -l # 显示主类全名 jps -v # 显示 JVM 启动参数 ``` **输出示例**: ```plaintext 1234 com.example.MyApp -Xmx1024m 5678 sun.tools.jps.Jps ``` --- #### **(2) `jstat`:实时监控 JVM 状态** **常用命令**: ```bash jstat -gcutil <PID> 1000 10 # 每秒采样一次,共10次(监控 GC) jstat -class <PID> 1000 # 监控类加载/卸载 ``` **关键参数**: - `-gcutil`:各内存区域使用率(Eden, Old, Survivor)及 GC 时间占比。 - `-gccapacity`:各内存区域容量。 - `-printcompilation`:JIT 编译统计。 **输出示例(`-gcutil`)**: ```plaintext S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 99.80 85.23 75.45 95.12 90.33 15 0.250 3 1.200 1.450 ``` **指标解析**: - `YGC/YGCT`:Young GC 次数/总耗时。 - `FGC/FGCT`:Full GC 次数/总耗时(频繁 Full GC 可能预示内存泄漏)。 --- #### **(3) `jstack`:线程快照分析** ```bash jstack <PID> > thread_dump.txt # 生成线程快照 ``` **分析场景**: - **死锁检测**:搜索输出中的 `deadlock` 关键字。 - **线程阻塞**:查看 `BLOCKED` 状态的线程及堆栈。 - **高 CPU 占用**:结合 `top -H -p <PID>` 找到高 CPU 线程,转换为 16 进制后匹配线程 ID。 --- #### **(4) `jmap`:内存分析与堆转储** **生成堆转储**: ```bash jmap -dump:format=b,file=heap.hprof <PID> # 生成二进制堆转储文件 ``` **查看内存对象分布**: ```bash jmap -histo <PID> # 统计对象实例数量及内存占用 ``` **输出示例**: ```plaintext num #instances #bytes class name ---------------------------------------------- 1: 1000000 200000000 [B (byte数组) 2: 500000 120000000 java.lang.String ``` --- #### **(5) `jcmd`:一体化诊断工具(JDK 7+)** ```bash jcmd <PID> help # 查看支持的命令 jcmd <PID> VM.flags # 查看 JVM 参数 jcmd <PID> GC.heap_info # 打印堆内存信息 jcmd <PID> Thread.print # 等同于 jstack jcmd <PID> GC.run_finalization # 主动触发 finalize() ``` --- ### **3. 典型问题排查流程** #### **场景 1:应用卡顿(GC 问题)** 1. **监控 GC**: ```bash jstat -gcutil <PID> 1000 5 ``` - 观察 `FGC/FGCT` 是否频繁增长,`Old 区`使用率是否持续高位。 2. **生成堆转储**: ```bash jmap -dump:format=b,file=heap.hprof <PID> ``` 3. **分析工具**: - 使用 Eclipse MAT 或 VisualVM 分析 `heap.hprof`,查找内存泄漏对象。 --- #### **场景 2:CPU 使用率飙升** 1. **定位高 CPU 线程**: ```bash top -H -p <PID> # Linux jstack <PID> > thread_dump.txt ``` 2. **转换线程 ID**: - 将 `top` 中的线程 ID(十进制)转为十六进制(如 `31526` → `0x7b06`)。 3. **分析线程堆栈**: - 在 `thread_dump.txt` 中搜索 `nid=0x7b06`,查看线程执行代码。 --- #### **场景 3:线程死锁** 1. **生成线程快照**: ```bash jstack <PID> > thread_dump.txt ``` 2. **搜索死锁**: ```bash grep -A 10 "deadlock" thread_dump.txt ``` 3. **分析锁竞争**: - 查看持有锁的线程及等待锁的线程堆栈。 --- ### **4. 高级工具补充** - **VisualVM**:图形化监控工具(支持本地/远程 JVM),可分析堆转储、线程快照。 - **Arthas**:阿里开源的 Java 诊断工具,支持实时方法追踪、热修复。 - **async-profiler**:低开销的 CPU/内存性能分析工具。 --- ### **5. 注意事项** - **权限要求**:监控工具需与目标 JVM 使用相同用户权限运行。 - **性能影响**:`jmap -dump` 可能导致应用短暂停顿(尤其在 Full GC 时)。 - **线上谨慎操作**:避免直接在生产环境执行高风险命令(如强制 GC)。 --- ### **总结** - **核心工具**:`jps`(定位进程)→ `jstat`(实时监控)→ `jstack/jmap`(深入分析)。 - **核心指标**:GC 频率、内存区域使用率、线程状态。 - **进阶方向**:结合堆转储与线程快照,使用 MAT/VisualVM 可视化分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值