jvm常用监控和诊断工具

jvm常用监控和诊断工具有jps, jstat, jmap,jstck, jcmd。

jps命令

jps命令用于查看正在运行的Java进程, 进程Id在jstat,jmap,jcmd等命令下会经常用到
语法:jps [-q] [-mlvV] [<hostid>]
常用:jpsjps -lv ; jps能够查看正在运行的java进程, -l是列出全路径,-v是列出启动参数
例子:

C:\Users\Lenovo>jps
22080 OomTest
29040 Main
25812
14888 Jps
29628 Launcher
C:\Users\Lenovo>jps -l
19280 sun.tools.jps.Jps
22080 com.xmc.demo.test.OomTest
29040 org/netbeans/Main
25812
29628 org.jetbrains.jps.cmdline.Launcher
C:\Users\Lenovo>jps -v
13808 OomTest2 -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/dump.hprof -javaagent:D:\IntelliJ IDEA 2020.2.1\lib\idea_rt.jar=14014:D:\IntelliJ IDEA 2020.2.1\bin -Dfile.encoding=UTF-8

jstat命令

jstat是用于监视虚拟机各种运行状态信息的命令行工具,它可以显示本地或远程虚拟机的类装载,内存,垃圾收集等信息在没有GUI图形界面工具的linux系统上,它是首选工具,常常用于检测垃圾回收及内存泄漏问题。
语法:jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
语法说明:<option>表示选型,vmid即java进程id,可以通过jps命令查找, interval 表示每隔多少毫秒输入, count表示一共输出多少次。

常用的option选项有类型:
类装载信息相关: -class
垃圾回收相关:
-gc 显示与GC相关的堆信息,包括Eden,Survior, 老年代,永久代,元空间等的大小,可用大小等信息。
-gcutil 显示内容与-gc类似,但输出内容主要关注已使用空间占总空间的比例。
-gccause 显示内容与 -gcutil类似,但是多了当前GC的原因
-gcnew 显示新生代的gc情况
-gcold 显示老年代的gc情况
例子:

C:\Users\Lenovo>jps
29040 Main
25812
28052 Jps
21640 Launcher
26140 OomTest2

C:\Users\Lenovo>jstat -gc 26140
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
512.0  512.0  496.0   0.0    2048.0   194.2     7168.0     1121.4   4864.0 4010.6 512.0  440.5       2    0.003   0      0.000    0.003

C:\Users\Lenovo>jstat -gcutil 26140
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
 96.88   0.00   9.48  15.64  82.45  86.03      2    0.003     0    0.000    0.003

C:\Users\Lenovo>jstat -gccause 26140
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
 96.88   0.00   9.48  15.64  82.45  86.03      2    0.003     0    0.000    0.003 Allocation Failure   No GC

C:\Users\Lenovo>jstat -gcnew 26140
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
 512.0  512.0  496.0    0.0  7  15  512.0   2048.0    194.2      2    0.003

C:\Users\Lenovo>jstat -gcold 26140
   MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT
  4864.0   4010.6    512.0    440.5      7168.0      1121.4      2     0    0.000    0.003
# 每个1秒输出一次,一共输入5次
C:\Users\Lenovo>jstat -gc 25740 1000 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
512.0  512.0  504.0   0.0    2048.0   186.1     7168.0     1067.4   4864.0 4011.2 512.0  440.5       2    0.002   0      0.000    0.002
512.0  512.0  504.0   0.0    2048.0   186.1     7168.0     1067.4   4864.0 4011.2 512.0  440.5       2    0.002   0      0.000    0.002
512.0  512.0  504.0   0.0    2048.0   186.1     7168.0     1067.4   4864.0 4011.2 512.0  440.5       2    0.002   0      0.000    0.002
512.0  512.0  504.0   0.0    2048.0   186.1     7168.0     1067.4   4864.0 4011.2 512.0  440.5       2    0.002   0      0.000    0.002
512.0  512.0  504.0   0.0    2048.0   186.1     7168.0     1067.4   4864.0 4011.2 512.0  440.5       2    0.002   0      0.000    0.002

S0C表示survior0的大小, S1C表示survior1的大小, S0U表示survior0的使用大小, EC表示Eden区的大小,EU表示Eden区已经使用的带下, OC表示老年代的大小,OU表示老年代已使用大小,MC表示方法区大小,MU表示方法区已使用大小YGC表示young GC次数,YGCT表示young GC耗时, FGCT表示Full GC次数, FGCT表示full GC耗时, GCT表示GC总耗时(即YGCT + FGCT)。
大小512这些都是Kb,我在这个类启动的时候设置了堆大小-Xms10m -Xmx10m 是10m,默认的新生代与老年代的比例是1:2,就是说新生代大概是3M,老年代大概是7M;新生代中的Eden区与S0,S1的比例是8:1:1,这里大概看到的就是2048:512:512,有点不符合(这里可能是jvm动态调整了比例,除非显式设置比Eden区与survior区的比例),但是总体上看还是满足Eden区比s0和s1大的特点。

通过每隔多少秒把堆信息和GC信息打出来,如果是短时间内多次Full GC,但是Full GC之后老年代的内存还不释放,意味着就内存泄漏的情况(程序执行了,对象没办法释放,导致内存被占用,比如一个全局的静态list一直在添加对象,这个list没办法被回收)。

jmap命令

jmap导出dump文件,dump文件用于查看java堆的使用情况,对象,类等信息。dump文件导出后可以用visual VM等工具查看。
语法:jmap [option] <pid>
option说明:
-heap 输出堆信息,包括GC,内存使用情况。
-dump 用于生成dump文件
-histo[:live] 输出堆中的对象统计信息,包括类,实例数量合计数量等。 :live表示只统计堆中存活的对象。
常用命令:
手动导出:jmap -dump:format=b,file=dumpName.hprof 进程id format=b表示的是dump文件的格式是hprof类型,只需要把file后面的文件路径和文件名称修改一下就能使用了
程序发生OOM时自动导出:-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/dump.hprof
例如在java程序配置如下参数,当堆超过100m导致程序崩溃的时候会输出dump文件:-Xmx100m -Xms100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/dump.hprof
例子:

C:\Users\Lenovo>jmap -heap 25740
Attaching to process ID 25740, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.171-b11

using thread-local object allocation.
Parallel GC with 13 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 10485760 (10.0MB)
   NewSize                  = 3145728 (3.0MB)
   MaxNewSize               = 3145728 (3.0MB)
   OldSize                  = 7340032 (7.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 2097152 (2.0MB)
   used     = 1947192 (1.8569869995117188MB)
   free     = 149960 (0.14301300048828125MB)
   92.84934997558594% used
From Space:
   capacity = 524288 (0.5MB)
   used     = 32768 (0.03125MB)
   free     = 491520 (0.46875MB)
   6.25% used
To Space:
   capacity = 524288 (0.5MB)
   used     = 0 (0.0MB)
   free     = 524288 (0.5MB)
   0.0% used
PS Old Generation
   capacity = 7340032 (7.0MB)
   used     = 4323504 (4.1232147216796875MB)
   free     = 3016528 (2.8767852783203125MB)
   58.903067452566965% used

5919 interned Strings occupying 497608 bytes.

jmap -histo:live 25740 执行后看一下有几千个类,我只列出部分。

C:\Users\Lenovo>jmap -histo:live 25740

 num     #instances         #bytes  class name
----------------------------------------------
   1:          8571         802080  [C
   2:           705         328512  [B
   3:          1830         206632  java.lang.Class
   4:          8410         201840  java.lang.String
   5:           931         155520  [I
   6:          1819          97664  [Ljava.lang.Object;
   7:           464          40832  java.lang.reflect.Method
   8:          1156          36992  java.util.HashMap$Node
   9:           881          35240  java.util.TreeMap$Entry
  10:           206          20768  [Ljava.util.HashMap$Node;
  11:           489          19560  java.lang.ref.SoftReference
  12:           512          18896  [Ljava.lang.String;
  13:           319          15312  java.util.HashMap
  14:           370          14800  java.util.LinkedHashMap$Entry
  15:           443          14176  java.util.concurrent.ConcurrentHashMap$Node
  16:           219          14016  java.net.URL
  17:           319          12760  java.lang.ref.Finalizer
  18:           201          11256  java.lang.invoke.MemberName

导出堆的dump文件,在生产或测试环境导出后先压缩(一般来说都有几百M),然后再拿到window本地解压使用visual VM等工具进行查看

C:\Users\Lenovo>jmap -dump:format=b,file=d:\aa.hprof 30136
Dumping heap to D:\aa.hprof ...
Heap dump file created
C:\Users\Lenovo>jmap -dump:live,format=b,file=D:\bb.hprof 30136
Dumping heap to D:\bb.hprof ...
Heap dump file created

测试代码:

public class OomTest2 {
    public static void main(String[] args) throws InterruptedException {
        List<byte[]> list = new ArrayList<>();
        while (true) {
            User user = new User();
            user.setName("11234ac");
            list.add(new byte[1024]);
            Thread.sleep(20);
        }
    }
}

项目启动参数-Xms5m -Xmx5m -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/dump.hprof,当发生OOM后会自动把dump文件输出到D:/dump.hprof
在这里插入图片描述
在这里插入图片描述

jstack命令

jstack查看线程快照,可以通过jstacck获取的线程快照来分析线程长时间停顿的原因,如死锁,死循环,请求外部资源导致的长时间等待等。一般来说用得比较少,都是用分布式锁了。如果程序还是比较多的synchronized和Lock这类型jvm的锁,则可以通过jstack命令帮助我们解决问题。
重点关注:DeadLock, Waiting on condition,Waiting on monitor entry, Blocked 这几种情况,这些情况都是非正常情况。
语法:jstack 进程id

C:\Users\Lenovo>jstack 13808
2022-08-20 21:27:26
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.171-b11 mixed mode):

"Service Thread" #19 daemon prio=9 os_prio=0 tid=0x0000000017956800 nid=0x34a8 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread11" #18 daemon prio=9 os_prio=2 tid=0x00000000179cf800 nid=0x77f4 waiting on condition [0x0000000000000000]
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001420e000 nid=0x71d8 in Object.wait() [0x000000001753e000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000fffa5d90> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000fffa5d90> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"main" #1 prio=5 os_prio=0 tid=0x0000000003665000 nid=0x6c74 waiting on condition [0x00000000033ef000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.xmc.demo.test.OomTest2.main(OomTest2.java:23)

"VM Thread" os_prio=2 tid=0x0000000015c84800 nid=0x3c9c runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x000000000367b800 nid=0x5ec8 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000000000367d000 nid=0x6384 runnable

jcmd命令

jcmd 是jkd1.7之后官方提供的一个多功能的工具, 用来实现除了jstat之外的所有功能,如jps,jmap,jstack,官方推荐使用jcmd命令替代jmap命令。
语法:jcmd -l 列出所有的java进程,相当于jps
jcmd 进程id help 列出该进程支持的命令
例子:

C:\Users\Lenovo>jcmd 13808 help
13808:
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
GC.rotate_log
Thread.print
GC.class_stats
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help
#输出dump文件
C:\Users\Lenovo>jcmd 13808 GC.heap_dump D:/ccc.hprof
13808:
Heap dump file created
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值