JVM监控工具

简介: Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。

jps


查看系统中运行的java进程id


PS D:\practise\test> jps
22672 Jps
13688 RemoteMavenServer36
1068 
14188 TestApplication
PS D:\practise\test> 

jmap


用来查看进行内存信息,实例个数以及占用内存大小


jmap -histo 进程id
PS D:\practise\test> jmap -histo 14188

 num     #instances         #bytes  class name
----------------------------------------------
   1:        131071       49867776  [B
   2:        241900       26780880  [C
   3:         19253       16120104  [I
   4:        130495        3131880  java.lang.String
   5:         22646        1339888  [Ljava.lang.Object;
   6:         54772        1152528  [Ljava.lang.Class;
   7:         12544        1103872  java.lang.reflect.Method
   8:          6356         704152  java.lang.Class
   9:         10415         583240  jdk.internal.org.objectweb.asm.Item
   ...
   ...
   ...
   3445:             1             16  sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter
   3446:             1             16  sun.util.resources.LocaleData
   3447:             1             16  sun.util.resources.LocaleData$LocaleDataResourceBundleControl

instances:对应对象的实例个数


bytes:占用内存大小


class name:对应的class名称,其中 [B [C [I 代表 byte[],char[], int[]


如 4: 130495 3131880 java.lang.String


代表String对象共有130495个,共张红3131880个字节大小。


jmap -heap 进程id (查看堆信息)



PS D:\practise\test> jmap -heap 14188 

Attaching to process ID 14188, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.261-b12

using thread-local object allocation.
Parallel GC with 10 thread(s)
//堆的配置信息
Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 8547991552 (8152.0MB) //最大堆内存
   NewSize                  = 178257920 (170.0MB)   //新生代空间
   MaxNewSize               = 2848980992 (2717.0MB) //最大的新生代空间 (默认新生代占1/3,老年代占2/3)
   OldSize                  = 356515840 (340.0MB)   //老年代空间
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)//元空间大小
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB     //元空间最大大小,元空间有动态伸缩机制,可以无限大。
   G1HeapRegionSize         = 0 (0.0MB)             //G1垃圾收集器region大小
//堆使用信息
Heap Usage:
PS Young Generation
Eden Space:
   capacity = 134217728 (128.0MB)
   used     = 98601000 (94.03324127197266MB)
   free     = 35616728 (33.966758728027344MB)
   73.46346974372864% used
From Space:  //SURVIVOR区1
   capacity = 22020096 (21.0MB)
   used     = 0 (0.0MB)
   free     = 22020096 (21.0MB)
   0.0% used
To Space:   //SURVIVOR区2
   capacity = 22020096 (21.0MB)
   used     = 0 (0.0MB)
   free     = 22020096 (21.0MB)
   0.0% used
PS Old Generation
   capacity = 240648192 (229.5MB)
   used     = 15842152 (15.108253479003906MB)
   free     = 224806040 (214.3917465209961MB)
   6.583116984315428% used

14390 interned Strings occupying 1282064 bytes.

jmap -dump:format=b,file=filename.hprof 进程id (将堆当前时刻快照信息dump到文件中)
PS D:\practise\test> jmap -dump:format=b,file=test.hprof 14188
Dumping heap to D:\practise\test\test.hprof ...
Heap dump file created
PS D:\practise\test>

利用jvisualvm命令,文件,装入文件,将dump出的文件进行分析



也可以设置内存溢出自动导出dump文件(内存很大的时候,可能会导致导出失败)


-XX: +HeapDumpOnOutOfMemoryError


-XX: +HeapDumpPath=./(导出路径)


public class OomTest {

    public static List<Object> list = new ArrayList<>();

    /**
     * -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\jvm.dump
     * @param args
     */
    public static void main(String[] args) {
        while(true){
            list.add(new Object());
        }
    }
}

oom导出dump文件通过jvisualvm装入打开



可以看出异常线程



JSTACK

jstack 进程id

打印java进程详细的堆栈跟踪信息

jstack 查看死锁信息
public class DeadLock {

    private static final Object lock1 = new Object();
    private static final Object lock2 = new Object();

    public static void main(String[] args) {
        new  Thread(() -> {
            synchronized (lock1) {
                try {
                    System.out.println("thread1 begin");
                    Thread.sleep(5000);

                } catch (InterruptedException e){}
                synchronized (lock2){
                    System.out.println("thread1 end");
                }
            }
        }).start();

        new  Thread(() -> {
            synchronized (lock2) {
                try {
                    System.out.println("thread2 begin");
                    Thread.sleep(5000);
                } catch (InterruptedException e){}
                synchronized (lock1){
                    System.out.println("thread2 end");
                }
            }
        }).start();
    }
}

PS D:\code-base\code-base\code-base> jps
15984 RemoteMavenServer36
1780 
20516 Launcher
7476 Jps
7508 DeadLock
20812 Main
PS D:\code-base\code-base\code-base> jstack 7508
2024-03-12 10:22:40
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.261-b12 mixed mode):


"JMX server connection timeout 19" #19 daemon prio=5 os_prio=0 tid=0x0000016e833bd000 nid=0x4edc in Object.wait() [0x00000001d89ff000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
        - locked <0x0000000717fab328> (a [I)
        at java.lang.Thread.run(Thread.java:748)
...
...

JNI global references: 339

//发现一个java级别的死锁
Found one Java-level deadlock:
=============================
"Thread-1":
  //thread-1等待0x0000016efff21d48的监控锁,被thread-0持有
  waiting to lock monitor 0x0000016efff21d48 (object 0x000000071644d0a8, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  //thread-0等待0x0000016efff1f4b8的监控锁,被thread-1持有
  waiting to lock monitor 0x0000016efff1f4b8 (object 0x000000071644d0b8, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at cn.axj.jvm.memory.DeadLock.lambda$main$1(DeadLock.java:42)
        - waiting to lock <0x000000071644d0a8> (a java.lang.Object)
        - locked <0x000000071644d0b8> (a java.lang.Object)
        at cn.axj.jvm.memory.DeadLock$$Lambda$2/1747585824.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)
"Thread-0":
        at cn.axj.jvm.memory.DeadLock.lambda$main$0(DeadLock.java:24)
        - waiting to lock <0x000000071644d0b8> (a java.lang.Object)
        - locked <0x000000071644d0a8> (a java.lang.Object)
        at cn.axj.jvm.memory.DeadLock$$Lambda$1/1096979270.run(Unknown Source)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

jstack找出占用cpu最高的线程堆栈信息


1. TOP -p <pid> //查看占用cpu最高的java进程

2. 按H查看详细的线程信息,找出占用最高cpu的线程id

3. 将线程id转换成16进制(由于jstack命令展示的线程id是16进制)

4. jstack 线程id | grep -A 10 16进制的线程id ,查看详细的堆栈信息

jinfo


查看正在运行的java应用程序的扩展参数


查看jvm参数
jinfo -flags <pid>

PS D:\workspace> jinfo -flags 21208
Attaching to process ID 21208, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.261-b12
Non-default VM flags: -XX:-BytecodeVerificationLocal -XX:-BytecodeVerificationRemote -XX:CICompilerCount=4 -XX:InitialHeapSize=534773760 -XX:+ManagementServer -XX:MaxHeapSize=8547991552 -XX:MaxNewSize=2848980992 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=178257920 -XX:OldSize=356515840 -XX:TieredStopAtLevel=1 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:56474,suspend=y,server=n -XX:TieredStopAtLevel=1 -Xverify:none -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\aoxiaojun\AppData\Local\JetBrains\IntelliJIdea2023.1\captureAgent\debugger-agent.jar=file:/C:/Users/aoxiaojun/AppData/Local/Temp/capture.props -Dfile.encoding=UTF-8
查看java系统参数
jinfo -sysprops <pid>

jstat


jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。

jstat [-命令选项][vmid][间隔时间(毫秒)][查询次数]
垃圾回收统计
jstat -gc <pid> 最常用,可以评估程序内存使用及GC压力整体情况
PS D:\workspace> jstat -gc 21208
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
36864.0 34816.0  0.0   27523.8 929280.0 794497.3  428544.0   68908.8   81560.0 78200.9 9640.0 8981.8     15    0.239   3      0.228    0.467


S0C: SUVIVOR区0的容量


S1C: SUVIVOR区1的容量


S0U: SUVIVOR区0的使用量


S1U: SUVIVOR区1的使用量


EC: eden的容量


EU: eden的使用量


OC: OLD的容量


OU: OLD的使用量


MC: 元空间的容量


MU: 元空间的使用量


CCSC,CCSU: 压缩指针


YGC: youngGC的次数(从启动开始)


YGCT: youngGCTime ,总共花费了多少时间


FGC: FULL GC次数


FGCT: FULL GC花费的总时间


GCT: 总的GC花费的时间(YGCT + FGCT)


堆内存统计


jstat -gccapacity <pid>
新生代内存统计
jstat -gcnewcapacity <pid>
老年代垃圾回收统计
jstat -gcold <pid>

JVM运行情况预估


用 jstat gc -pid 命令可以计算出如下一些关键数据,有了这些数据就可以采用之前介绍过的优化思路,先给自己的系统设置一些初始性的JVM参数,比如堆内存大小,年轻代大小,Eden和Survivor的比例,老年代的大小,大对象的阈值,大龄对象进入老年代的阈值等。


年轻代对象增长的速率


可以执行命令 jstat -gc pid 1000 10(每隔1秒执行1次命令,共执行10次),通过观察EU(eden区的使用)来估算每秒eden大概新增多少对象,如果系统负载不高,可以把频率1秒换成1分钟,甚至10分钟来观察整体情况。注意,一般系统可能有高峰期和日常期,所以需要在不同的时间分别估算不同情况下对象增长速率。


Young GC的触发频率和每次耗时


知道年轻代对象增长速率我们就能推根据eden区的大小推算出Young GC大概多久触发一次,Young GC的平均耗时可以通过 YGCT/YGC 公式算出,根据结果我们大概就能知道``系统大概多久会因为Young GC的执行而卡顿多久。`


每次Young Gc后有多少对象存活和进入老年代


这个因为之前已经大概知道Young GC的频率,假设是每5分钟一次,那么可以执行命令jstat -gc pid 300000 10,观察每次结果eden,survivor和老年代使用的变化情况,在每次gc后eden区使用一般会大幅减少,survivor和老年代都有可能增长,这些增长的对象就是每次Young GC后存活的对象,同时还可以看出每次Young GC 后进去老年代大概多少对象,从而可以推算出老年代对象增长速率。


FuIl GC的触发频率和每次耗时


知道了老年代对象的增长速率就可以推算出Full GC的触发频率了,Full GC的每次耗时可以用公式 FGCT/FGC 计算得出。


优化思路其实简单来说就是尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里,尽量别让对象进入老年代。尽量减少FuIl GC的频率,避免频繁Full GC对JVM性能影响。


JVISUALVM


java进程可视化监视工具,集成上面的命令


在生产环境中禁用,而且JVISUALVM远程链接生产服务器会多开端口,可能会带来安全问题。


arthas


Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。


官方文档地址


目录
相关文章
|
4月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
412 3
|
1月前
|
JavaScript 前端开发 Java
jvm的jshell,学生的工具
本文介绍了JVM的jshell工具,它为Java平台添加了REPL(读取-评估-打印循环)功能,使得学习、探索编码和原型代码变得更加便捷,但作者认为其在实际开发中较为鸡肋。
30 1
jvm的jshell,学生的工具
|
24天前
|
Arthas 监控 数据可视化
JVM进阶调优系列(7)JVM调优监控必备命令、工具集合|实用干货
本文介绍了JVM调优监控命令及其应用,包括JDK自带工具如jps、jinfo、jstat、jstack、jmap、jhat等,以及第三方工具如Arthas、GCeasy、MAT、GCViewer等。通过这些工具,可以有效监控和优化JVM性能,解决内存泄漏、线程死锁等问题,提高系统稳定性。文章还提供了详细的命令示例和应用场景,帮助读者更好地理解和使用这些工具。
|
1月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
49 2
|
1月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
41 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
3月前
|
缓存 监控 算法
吃透 JVM 诊断方法与工具使用
【8月更文挑战第4天】深入了解并掌握JVM诊断需把握几大要点:1) 熟悉JVM内存模型,如堆、栈及方法区;2) 掌握垃圾回收机制与算法;3) 运用工具如`jps`(查看Java进程)、`jstat`(监控运行状态)、`jmap`(生成堆快照)、`jhat`(分析堆快照)、`jstack`(检查线程栈); 4) 利用专业工具如Eclipse Memory Analyzer分析堆转储文件查找内存泄漏; 5) 动态监控与调整JVM参数; 6) 结合日志分析性能瓶颈。通过实战案例加深理解,有效应对JVM性能问题。
|
4月前
|
运维 监控 Java
(十)JVM成神路之线上故障排查、性能监控工具分析及各线上问题排错实战
经过前述九章的JVM知识学习后,咱们对于JVM的整体知识体系已经有了全面的认知。但前面的章节中,更多的是停留在理论上进行阐述,而本章节中则更多的会分析JVM的实战操作。
107 1
|
3月前
|
Arthas Prometheus 监控
使用JDK自带工具调优JVM的常用命令
使用JDK自带工具调优JVM的常用命令
|
4月前
|
监控 Java 开发者
Java面试题:如何使用JVM工具(如jconsole, jstack, jmap)来分析内存使用情况?
Java面试题:如何使用JVM工具(如jconsole, jstack, jmap)来分析内存使用情况?
202 2
|
3月前
|
监控 Java Android开发
吃透 JVM 诊断方法与工具使用
【8月更文挑战第3天】要精通JVM诊断,需掌握关键监控指标如内存(堆/非堆)、CPU使用及线程状态;熟悉工具如`jstat`(监控状态)、`jmap`(堆转储)、`jstack`(线程堆栈);并能利用Eclipse Memory Analyzer (MAT)分析堆转储找内存泄漏;同时理解GC日志以优化垃圾回收行为;通过实践案例加深理解。