橘子学JVM之命令行监控02之jstat

一、简介

jstat:查看JVM统计信息

jstat(JVM Statistics Monitoring Tool):用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。常用于检测垃圾回收问题以及内存泄漏问题。

官方文档:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html

基本使用语法为:jstat - [-t] [-h] [ []]
在这里插入图片描述
查看命令相关参数:jstat-h 或 jstat-help
其中vmid是进程id号,也就是jps之后看到的前面的号码,如下:
橘子学JVM之命令行监控02之jstat_第1张图片
我们看到上面的指令语法,那些中括号括起来的都是可以不加可以加的。其中-option有多种格式。下面来一一看一下。

二、参数详细

1、参数详解

option参数
选项option可以由以下值构成。

类装载相关的:
● -class:显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等

垃圾回收相关的:
● -gc:显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。
● -gccapacity:显示内容与-gc基本相同,但输出主要关注Java堆各个区域使用到的最大、最小空间。
● -gcutil:显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。
● -gccause:与-gcutil功能一样,但是会额外输出导致最后一次或当前正在发生的GC产生的原因。
● -gcnew:显示新生代GC状况
● -gcnewcapacity:显示内容与-gcnew基本相同,输出主要关注使用到的最大、最小空间
● -geold:显示老年代GC状况
● -gcoldcapacity:显示内容与-gcold基本相同,输出主要关注使用到的最大、最小空间
● -gcpermcapacity:显示永久代使用到的最大、最小空间。

JIT相关的:
● -compiler:显示JIT编译器编译过的方法、耗时等信息
● -printcompilation:输出已经被JIT编译的方法

因为option有这么多,但是其余的种类是不多的,所以我们只取一个option的参数和其余的进行搭配,先把其余的拿下,再回来看option剩下的,我们就选择class进行操作。

1、jstat -class vmid

我们指定一下进程id,进行分析他的class信息,我们看一下输出。
1、先看一下我的程序进程id是51048
在这里插入图片描述
然后执行jstat -class 51048
在这里插入图片描述
我们看到输出的信息如上图,他妈的水印太垃圾了,分别有这么几列

  • Loaded:代表该程序运行加载的类有多少个,有530个
  • Bytes:代表该程序运行加载的类的大小是1080.2字节
  • Unloaded:代表该程序当前也就是你输入命令统计那一刻的时候卸载了几个类
  • Bytes;代表当前程序你统计那一刻卸载类的大小是多少个字节
  • Time:代表你这次统计的耗时,也就是你执行这个命令的耗时是多少

2、jstat -class vmid interval

上面我们输出了一行数据,意思就是他采集了一次当前信息。假如我们想周期性的输出采集结果呢,比如我们想一秒采集一次,而不是就采集一次就完了。就可以指定这个interval的参数,翻译一下也是周期的意思。
我们执行jstat -class 51048 1000这个指令即可,1000的意思是1000毫秒,也就是一秒输出一次,不断的采集。
橘子学JVM之命令行监控02之jstat_第2张图片
但是呢,这个采集方式你指定了一秒一次,他就是不断的输出,一直不停,直到你的程序寄了。比如oom了。有时候我们想只采集5次就够了,那就可以指定interval后面的count参数,指定执行的次数。

3、jstat -class vmid interval count

我们执行jstat -class 51048 1000 5我们指定采集5次。我们看到了他就是输出了5次就完了。
橘子学JVM之命令行监控02之jstat_第3张图片

4、jstat -class -t vmid interval count

这个-t是会在前面加一列,意思是一个时间,time的意思,这个时间代表你的程序从启动到现在经过了多少秒。
我们执行一下jstat -class -t 51048 1000 5
在这里插入图片描述
我们看到前面有多了一列,就是你程序的执行时间。

5、jstat -class -t -h lines vmid interval count

这个-h的意思就是表头的意思,head后面那个lines就是几行就输出一个表头,假如我们指定为2我们看看啥效果。
橘子学JVM之命令行监控02之jstat_第4张图片
还有个规则,我们看一下这个完整的语句,
在这里插入图片描述
jstat -class -t -h lines vmid interval count
我们看到有的参数是有形参指定的比如-t 直接就是-t就知道是输出时间列的
比如-h后面加行数,这个行数代表的就是你-h的这个几行打一次表头。
但是后面的那种vmid interval count这个是没有前面的类似-h这种形参的,这就不好区分有的时候,比如你输入了一个jstat -class -t -h 2 51048 5
这时候后面这个5就是5毫秒输出一次,打印的刷刷的很快,不是代表的一共输出5次了,这里有个顺序问题,需要注意一下。

2、option参数详解

下面的这些option参数和-class一样,也可以和后面那些参数一起使用。

2.1、JIT相关信息采集

jstat -compiler
我们执行一下jstat -compiler 线程id,我们先看一下程序的线程id是54400
在这里插入图片描述
接下来我们用jstat采集信息。
在这里插入图片描述
以上采集结果的输出各行分别代表的意思是:

  • Compiled :表示jit优化编译了28个方法或者是结构
  • Failed:表示编译失败了0个
  • Inbalid:表示编译无效的个数是0
  • Time:表示编译花费的时间
  • 后面是编译失败的类型和编译失败的方法

jstat -printcompilation
橘子学JVM之命令行监控02之jstat_第5张图片
我们看到编译了28个结构,大小是5,编译的具体方法就是get方法,这里还需要处理一下TODO

2.2、gc相关信息采集

-gc
显示与GC相关的堆信息。包括Eden区、两个Survivor区、老年代、永久代等的容量、已用空间、GC时间合计等信息。

我们执行一下这个jstat -gc 1556 1000 5表示监控一下1556号线程的gc信息,没秒采集一次,一共采集五次。
在这里插入图片描述
我们依次说一下这几列的表头含义。

S0C:表示当前你这个程序启动时候设置的s0区的总大小。
S1C:表示当前你这个程序启动时候设置的s1区的总大小。c我理解就是个count的意思。

S0U:表示当前你这个程序采集的时候s0区已经使用了的大小。
S1U:表示当前你这个程序采集时候s1区已经使用了的大小,U我理解就是use使用的意思。

EC:表示当前你这个程序采集的时候eden区设置的大小。
EU:表示当前你这个程序采集时候eden区已经使用了的大小.。

OC:表示当前你这个程序采集的时候老年代设置的总大小。
OU:表示当前你这个程序采集时候老年代已经使用了的大小。

MC:表示当前你这个程序采集的时候方法区设置的总大小。
MU:表示当前你这个程序采集时候方法区已经使用了的大小。

CCSC:表示当前你这个程序采集的时候压缩类设置的总容量。
CCSU:表示当前你这个程序采集的时候压缩类已经使用的容量。

YGC:采集的时候youngGC发生的次数。
YGCT:采集的时候youngGC一共占用的时间。

FGC:采集的时候fullGC发生的次数。
FGCT:采集的时候fullGC一共占用的时间。

GCT:采集的时候一共GC的时间,也就是FGCT+YGCT

接下来我们就来关注一下GC的一个监控,但是呢上面的程序不太能反应gc变化,我们新开一个程序。

2.3、GC程序操作

/**
 * @author: levi
 * @description: -Xms60m -Xmx60m -XX:SurvivorRatio=8  堆空间初始和最大值设置为60m,s区和eden区的比例为8:1:1
 * @date: 2022-10-3 20:10
 * @version: 1.0
 */
public class GCtest {
    // 100KB大小
    static final int _100KB = 1024 * 100;
    public static void main(String[] args) {
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            // 每120毫秒就添加100KB进这个集合里面
            byte[] arr = new byte[_100KB];
            list.add(arr);
            try {
                Thread.sleep(120);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

-gc参数

启动程序,jps查看进程号后,开启监控。
在这里插入图片描述
我们先分析一下,我们看到s0和s1区的总大小都是2048字节,也就是2m。我大体分析一下。
我们设置堆空间是60m。默认的新生代和老年代的比例是1:2可以通过newRatio来控制。
也就是说新生代目前是占了三分之一,也就是20M,而eden区和s区的比例是8:1:1,所以s区每个占十分之一,也就是2m,也就是2048kb,可见是没啥问题的。
OK,这个-gc参数就是这么个意思,每个参数的意思都是如上所述。

jstat -gcutil 显示内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比。

我们执行一下jstat -gcutil 98920 1000 80 每秒采集一次,一共采集80次。
橘子学JVM之命令行监控02之jstat_第6张图片
他的这几列基本和-gc差不多,他是-gc的一个子集,他只反应占比例的哪几项。
s0表示s0区的当前占用比例
其余的也都是占比,后面的还是时间长度。

jstat -gccapacity

jstat -gccause

jstat -gcnew

jstat -gcnewcapacity

jstat -gcold

jstat -gcoldcapacity

以上命令上面都有解释了,可以具体测试一下。

表头的解释下面有个列表可以看看、
橘子学JVM之命令行监控02之jstat_第7张图片

2.4、补充

1、关于gc时间的一个使用
我们每次采集的时候可以在-gc这类参数后面加上-t,每次输出你当前程序已经执行的时间,我们可以比较两次时间之间的GCT的时间,把这些GCT加起来,也就是你这个时间段里面GC一共耗费的时间,要是高于了百分之90那就说明你的程序可能随时要OOM要寄了。要是高于百分之20就说明有压力了,可以适当的针对性调优一下。
2、关于内存泄露
jstat还可以用来判断是否出现内存泄漏。

第1步:在长时间运行的 Java 程序中,我们可以运行jstat命令连续获取多行性能数据,并取这几行数据中 OU 列(即已占用的老年代内存)的最小值。

第2步:然后,我们每隔一段较长的时间重复一次上述操作(取多组数据,采样更加离散有参考性),来获得多组 OU 最小值。如果这些值呈上涨趋势,则说明该 Java 程序的老年代内存已使用量在不断上涨,这意味着无法回收的对象在不断增加,因此很有可能存在内存泄漏。

你可能感兴趣的:(#,JVM,jvm,java,linux)