我是靠谱客的博主 积极短靴,最近开发中收集的这篇文章主要介绍JVM(六) - JVM性能调优监控工具,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

在线上我们经常会遇见如下几个问题:

  • 内存泄露;
  • 某个进程突然 CPU 飙升;
  • 线程死锁;
  • 响应变慢。
    如果遇到了以上这种问题,在 线下环境 可以有各种 可视化的本地工具 支持查看。但是一旦到 线上环境,就没有这么多的 本地调试工具 支持,我们该如何基于 监控工具 来进行定位问题?

我们一般会基于 数据收集 来定位问题,而数据的收集离不开 监控工具 的处理,比如:运行日志、异常堆栈、GC 日志、线程快照、堆内存快照 等。为了解决以上问题,我们常用的 JVM 性能调优监控工具 大致有:jps、jstat、jstack、jmap、jhat、hprof、jinfo

1. jps进程监控工具

jps 是用于查看有权访问的 hotspot 虚拟机 的进程。当未指定 hostid 时,默认查看 本机 jvm 进程,否则查看指定的 hostid 机器上的 jvm 进程,此时 hostid 所指机器必须开启 jstatd 服务。

jps 可以列出 jvm 进程 lvmid,主类类名,main 函数参数, jvm 参数,jar 名称等信息。
命令格式如下:

usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

Definitions:
    <hostid>:      <hostname>[:<port>]
    
参数含义如下:
-q: 不输出 类名称、Jar 名称 和传入 main 方法的 参数;
-l: 输出 main 类或 Jar 的 全限定名称;
-m: 输出传入 main 方法的 参数;
-v: 输出传入 JVM 的参数。

jps

2. jinfo配置信息查看工具

jinfo(JVM Configuration info)这个命令作用是实时查看和调整 虚拟机运行参数。之前的 jps -v 命令只能查看到显示 指定的参数,如果想要查看 未显示 的参数的值就要使用 jinfo 命令。

Usage:
    jinfo [option] <pid>
        (to connect to running process)
    jinfo [option] <executable <core>
        (to connect to a core file)
    jinfo [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)
        
参数含义如下:
pid:本地 jvm 服务的进程 ID;
executable core:打印 堆栈跟踪 的核心文件;
remote server IP/hostname:远程 debug 服务的 主机名 或 IP 地址;
server id:远程 debug 服务的 进程 ID。

参数选项说明如下:

参数参数含义
flag输出指定 args 参数的值
flags不需要 args 参数,输出所有 JVM 参数的值
sysprops输出系统属性,等同于 System.getProperties()

jinfo

3. jstat信息统计监控工具

jstat命令可以查看堆内存各部分的使用量,以及加载类的数量。命令的格式如下:
jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
注意:使用的jdk版本是jdk8.

垃圾回收统计 -gc

jstat -gc pid 最常用,可以评估程序内存使用及GC压力整体情况
在这里插入图片描述

参数参数含义
S0C第一个幸存区的大小
S1C第二个幸存区的大小
S0U第一个幸存区的使用大小
S1U第二个幸存区的使用大小
EC伊甸园区的大小
EU伊甸园区的使用大小
OC老年代大小
OU老年代使用大小
MC方法区大小(元空间)
MU方法区使用大小
CCSC压缩类空间大小
CCSU压缩类空间使用大小
YGC年轻代垃圾回收次数
YGCT年轻代垃圾回收消耗时间,单位sFGC:老年代垃圾回收次数
FGCT老年代垃圾回收消耗时间,单位s
GCT垃圾回收消耗总时间,单位s

堆内存统计 -gccapacity

jstat -gccapacity pid
在这里插入图片描述

参数参数含义
NGCMN新生代最小容量
NGCMX新生代最大容量
NGC当前新生代容量
S0C第一个幸存区大小
S1C第二个幸存区的大小
EC伊甸园区的大小
OGCMN老年代最小容量
OGCMX老年代最大容量
OGC当前老年代大小
OC当前老年代大小
MCMN最小元数据容量
MCMX最大元数据容量
MC当前元数据空间大小
CCSMN最小压缩类空间大小
CCSMX最大压缩类空间大小
CCSC当前压缩类空间大小
YGC年轻代gc次数
FGC老年代GC次数

新生代垃圾回收统计 -gcnew

jstat -gcnew pid
在这里插入图片描述

参数参数含义
S0C第一个幸存区的大小
S1C第二个幸存区的大小
S0U第一个幸存区的使用大小
S1U第二个幸存区的使用大小
TT对象在新生代存活的次数
MTT对象在新生代存活的最大次数
DSS期望的幸存区大小
EC伊甸园区的大小
EU伊甸园区的使用大小
YGC年轻代垃圾回收次数
YGCT年轻代垃圾回收消耗时间

新生代内存统计 -gcnewcapacity

jstat -gcnewcapacity pid
在这里插入图片描述

参数参数含义
NGCMN新生代最小容量
NGCMX新生代最大容量
NGC当前新生代容量
S0CMX最大幸存1区大小
S0C当前幸存1区大小
S1CMX最大幸存2区大小
S1C当前幸存2区大小
ECMX最大伊甸园区大小
EC当前伊甸园区大小
YGC年轻代垃圾回收次数FGC:老年代回收次数

老年代垃圾回收统计 -gcold

jstat -gcold pid
在这里插入图片描述

参数参数含义
MC方法区大小
MU方法区使用大小
CCSC压缩类空间大小
CCSU压缩类空间使用大小
OC老年代大小
OU老年代使用大小
YGC年轻代垃圾回收次数
FGC老年代垃圾回收次数
FGCT老年代垃圾回收消耗时间
GCT垃圾回收消耗总时间

元数据空间统计 -gcmetacapacity

jstat -gcmetacapacity pid
在这里插入图片描述

参数参数含义
MCMN最小元数据容量
MCMX最大元数据容量
MC当前元数据空间大小
CCSMN最小压缩类空间大小
CCSMX最大压缩类空间大小
CCSC当前压缩类空间大小
YGC年轻代垃圾回收次数
FGC老年代垃圾回收次数
FGCT老年代垃圾回收消耗时间
GCT垃圾回收消耗总时间

各个内存的使用占比,垃圾回收时间和回收次数 -gcutil

jstat -gcutil pid
在这里插入图片描述

参数参数含义
S0幸存1区当前使用比例
S1幸存2区当前使用比例
E伊甸园区使用比例
O老年代使用比例
M元数据区使用比例
CCS压缩使用比例
YGC年轻代垃圾回收次数
FGC老年代垃圾回收次数
FGCT老年代垃圾回收消耗时间
GCT垃圾回收消耗总时间

4. jmap堆内存统计工具

jmap (JVM Memory Map) 命令用来查看 堆内存 使用状况,一般结合 jhat 使用,用于生成 heap dump 文件。jmap 不仅能生成 dump 文件,还可以查询 finalize 执行队列、Java 堆 和 元空间 metaspace 的详细信息,如当前 使用率、当前使用的是哪种 收集器 等等。

如果不使用这个命令,还可以使用 -XX:+HeapDumpOnOutOfMemoryError 参数来让虚拟机出现 OOM 的时候,自动生成 dump 文件。

实例个数以及占用内存大小 -histo

在这里插入图片描述

  • num:序号
  • instances:实例数量
  • bytes:占用空间大小
  • class name:类名称,[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][]

堆信息 -heap

在这里插入图片描述

参数对应启动参数参数含义
MinHeapFreeRatio-XX:MinHeapFreeRatioJVM堆最小空闲比率(default 40)
MaxHeapFreeRatio-XX:MaxHeapFreeRatioJVM堆最大空闲比率(default 70)
MaxHeapSizeXX:XmxJVM堆的最大大小
NewSize-XX:NewSizeJVM堆新生代的默认(初始化)大小
MaxNewSize-XX:MaxNewSizeJVM堆新生代的最大大小
OldSize-XX:OldSizeJVM堆老年代的默认(初始化)大小
NewRatio-XX:NewRatioJVM堆新生代和老年代的大小比例
SurvivorRatio-XX:SurvivorRatioJVM堆年轻代中Eden区与Survivor区的大小比值
MetaspaceSize-XX:MetaspaceSizeJVM元空间(metaspace)初始化大小
MaxMetaspaceSize-XX:MaxMetaspaceSizeJVM元空间(metaspace)最大大小
CompressedClass SpaceSize-XX:CompressedClass SpaceSizeJVM类指针压缩空间大小, 默认为1G
G1HeapRegionSize-XX:G1HeapRegionSize使用G1垃圾回收器时单个Region的大小,取值为1M至32M

堆内存 dump

dump 用于导出内存转储快照。常用的方式是通过 jmap 把进程 内存使用情况 dump 到文件中,再用 jhat 分析查看。jmap 进行 dump 的命令格式如下:

jmap -dump:format=b,file=dumpFileName

在这里插入图片描述

public class OOMTest {

    public static List<Object> list = new ArrayList<>();
    // JVM设置
    // ‐Xms10M ‐Xmx10M ‐XX:+PrintGCDetails ‐XX:+HeapDumpOnOutOfMemoryError ‐XX:HeapDumpPath=E:jvm.dump
     public static void main(String[] args) {
         List<Object> list = new ArrayList<>();
         int i = 0;
         int j = 0;
         while (true) {
             list.add(new User(i++, UUID.randomUUID().toString()));
             new User(j--, UUID.randomUUID().toString());
         }
     }
}

我们也可以用 jvisualvm 导入dump文件来分析
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.jstack堆栈跟踪工具

jstack 用于生成 java 虚拟机当前时刻的 线程快照。线程快照 是当前 java 虚拟机内 每一条线程 正在执行的 方法堆栈 的 集合。生成线程快照的主要目的是定位线程出现 长时间停顿 的原因,如 线程间死锁、死循环、请求外部资源 导致的 长时间等待 等等。

线程出现 停顿 的时候,通过 jstack 来查看 各个线程 的 调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。如果 java 程序 崩溃 生成 core 文件,jstack 工具可以通过 core 文件获取 java stack 和 native stack 的信息,从而定位程序崩溃的原因。

系统线程状态
在 dump 文件里,值得关注的 线程状态 有:

  • 死锁:Deadlock(重点关注)
  • 执行中:Runnable
  • 等待资源:Waiting on condition(重点关注)
  • 等待获取监视器:Waiting on monitor entry(重点关注)
  • 暂停:Suspended
  • 对象等待中:Object.wait() 或 TIMED_WAITING
  • 阻塞:Blocked(重点关注)
  • 停止:Parked

用jstack查找死锁,见如下示例

public class DeadLockTest {
    private static Object lock1 = new Object();
    private static 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();
        System.out.println("main thread end");
    }
}

在这里插入图片描述
“Thread-1” 线程名
prio=5 优先级=5
tid=0x000000001fa9e000 线程id
nid=0x2d64 线程对应的本地线程标识nid
runnable 线程状态

在这里插入图片描述

最后

以上就是积极短靴为你收集整理的JVM(六) - JVM性能调优监控工具的全部内容,希望文章能够帮你解决JVM(六) - JVM性能调优监控工具所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(74)

评论列表共有 0 条评论

立即
投稿
返回
顶部