有哪些JDK内置的性能分析工具可以使用?

2026-05-23 16:051阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2437个文字,预计阅读时间需要10分钟。

有哪些JDK内置的性能分析工具可以使用?

有时会遇到服务器CPU过载或程序卡死等问题,这类bug通常定位困难。这类问题往往隐藏得比较深,且可能具有偶发性,比较棘手。对此类问题,我们通常有一套固定的分析流程。

有时候碰到服务器CPU飙升或者程序卡死之类的问题,一般都不太好定位。这类bug一般都隐藏的比较深并且还可能是偶发性的,比较棘手。

对于此类问题,一般我们都有固定的分析流程。借助于JDK自带的一些分析工具,比如jstack、jmap、jstat一类的命令行工具,除此之外,还有jconsole、mat、jvisualvm这些图形界面分析工具。

有哪些JDK内置的性能分析工具可以使用?

这篇文章基于JDK8,操作系统是macOS 12.0.1

1、一些命令行分析工具

这些命令行分析工具都在jdk/bin目录下

解压jdk/lib/tool.jar可以得到上述工具的class文件

1.1 jps - JVM Process Status Tool

作用:列出正在运行的虚拟机进程,并显示虚拟机执行主类名称以及这些进程的本地虚拟机唯一ID。

第一个参数说明:

  • -q:默认携带的参数,显示进程ID。

  • -m:显示进程ID,主类名称,以及传入main方法的参数。

  • -l:显示进程ID,主类全名。

  • -v:显示进程ID,主类名称,以及传入JVM的参数。

  • -V:显示进程ID,主类名称。

[-mlvV]可以任意组合使用。

第二个参数说明:

  • hostid:服务器的ip地址。不指定的情况下,默认为当前服务器。如果要查看其他机器上的JVM进程,需要在待查看机器上启动jstatd。
1.2 jstat - JVM Statistics Monitoring Tool

作用:监视虚拟机各种运行状态信息,可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

命令格式:jstat -

参数说明

第一个参数:option,代表用户希望查询的虚拟机信息,主要分为3类:类装载、垃圾收集和运行期编译情况。具体选项如下:

  • -class:显示有关类加载器行为的统计信息。

  • -compiler:显示有关java hotspot vm即时编译器行为的统计信息。

  • -gc:显示有关垃圾收集堆行为的统计信息。

  • -gccapacity:显示有关各个垃圾回收代容量及其相应容量的统计信息。

  • -gccause:显示有关垃圾收集统计信息(同-gcutil),以及上一次和当前垃圾收集事件的原因。

  • -gcnew:显示新生代行为的统计信息。

  • -gcnewcapacity:显示有关新生代大小及其相应空间的统计信息。

  • -gcold:显示老年代行为的统计信息和元空间统计信息。

  • -gcoldcapacity:显示有关老年代大小的统计信息。

  • -gcmetacapacity:显示有关元空间大小的统计信息。

  • -gcutil:显示有关垃圾收集统计信息。

  • -printcompilation:显示java hotspot vm编译方法统计信息。

第二个参数:vmid。如果是本地虚拟机进程,那么vmid和本地虚拟机唯一ID是一致的。如果是远程虚拟机进程,那么vmid的格式是:protocol:lvmid[@hostname[:port]/servername]

第三个参数:interval。采样间隔,单位为s或ms,默认单位是ms,必须为整数。指定该参数,jstat命令将在每个间隔产生输出。

第四个参数:count。要显示的样本数。

import java.io.IOException; /** * -class: * Loaded:已加载的类数量。 * Bytes:已加载的kb数。 * Unloaded:卸载的类数量。 * Bytes:卸载的kb数。 * Time:执行类加载和卸载的耗时。 * * -compiler: * Compiled:执行的编译任务数。 * Failed:编译失败的任务数。 * Invalid:无效的编译任务数。 * Time:执行编译任务所花费的时间。 * FailedType:失败的编译类型。 * FailedMethod:失败的编译类名和方法。 */ public class Demo1_jstat { public static void main(String[] args) throws IOException { System.out.println("jstat"); System.in.read(); } }

启动上面的demo后

import java.io.IOException; /** * -gc: 垃圾收集的堆统计信息 * S0C:s0区的容量(kb) * S1C:s1区的容量(kb) * S0U:s0区的使用大小(kb) * S1U:s1区的使用大学(kb) * EC:eden区的容量(kb) * EU:eden区的使用大小(kb) * OC:老年代容量(kb) * OU:老年代的使用大小(kb) * MC:元空间的容量(kb) * MU:元空间的使用大小(kb) * CCSC:压缩的类空间容量(kb) * CCSU:使用的压缩类空间大小(kb) * YGC:新生代垃圾收集次数 * YGCT:新生代垃圾回收时间 * FGC:full gc收集次数 * FGCT:full gc垃圾回收时间 * GCT:总垃圾收集时间 * * -gcutil:垃圾收集统计信息 * S0:s0区的使用率 * S1:s1区的使用率 * E:eden区使用率 * O:老年代使用率 * M:元空间使用率 * CCS:压缩类空间使用率 * YGC:新生代gc次数 * YGCT:新生代gc耗费时间 * FGC:full gc次数 * FGCT:full gc耗费时间 * GCT:总垃圾收集时间 */ public class Demo2_jstat { // -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc public static void main(String[] args) throws IOException { final int _1MB = 1024 * 1024; // 申请2M的空间 byte[] b1 = new byte[2 * _1MB]; System.out.println("1111"); System.in.read(); // 申请2M的空间 byte[] b2 = new byte[2 * _1MB]; System.out.println("2222"); System.in.read(); // 申请2M的空间 byte[] b3 = new byte[2 * _1MB]; System.out.println("3333"); System.in.read(); } }

启动上面的程序之前,先指定一些jvm参数

-Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc

然后启动demo

刚启动时,程序会申请2M的数组,可以看到eden区的使用率是62.37%,ygc的值为0。

让程序申请第二个2M的数组,之后再查看堆内存信息

可以发现eden区的使用率达到了87.37%。

让程序申请第三个2M的数组,发现控制台输出提示

再查看堆内存信息

发现eden区的使用率降到了26.71,s1区使用率时70.80%,老年代的使用率是40%即4096kb也就是4M空间大小。同时ygc的次数是1,说明进行了一次ygc,并且把大对象放进了老年代中。

1.3 jinfo - Configuration Info For Java

作用:实时的查看和调整虚拟机各项参数。

命令格式:jinfo [option]

参数说明

第一个参数:option。

  • no options:输出全部的参数和系统属性。

  • -flag name:输出对应名称的参数。

  • -flag [+ | -] name:开启或者关闭对应名称的参数。

  • -flag name=value:设置对于名称参数的参数值。

  • -flags:输出全部的参数。

  • -sysprops:输出全部的系统属性。

命令演示

  • jinfo pid

  • jinfo -flag PrintGCDetails pid (输出PrintGCDetails参数的值)

  • jinfo -flag +PrintGCDetails pid (开启PrintGCDetails参数)

  • jinfo -flag HeapDumpPath=/ pid (设置HeapDumpPath参数的值)

在我电脑上使用这个命令会报错,据说是macOS的一个bug,需要升级到jdk9,懒得升了。bug链接

1.4 jmap - Memory Map For Java

作用:一个多功能的命令,它可以生成Java程序的dump文件,也可以查看堆内对象的信息、classloader的信息和finalizer队列。

命令格式:jmap [option]

参数解释

第一个参数:option

  • no option:查看进程的内存镜像信息。

  • -heap:显示Java堆详细信息。

  • -histo[:live]:显示堆中对象的统计信息。

  • -clstats:打印类加载器信息。

  • -finalizerinfo:显示在F-Queue队列等待Finalizer线程执行finaizer方法的对象。

  • -dump::生成堆转储快照。

命令演示

  • jamp pid。打印出虚拟机加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。

  • jamp -heap pid。打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和各内存区域内存使用信息。

  • jmap -histo:live pid。显示堆中对象的统计信息,包括每个Java类型,对象数量,内存大小(单位字节),完全限定的类名。打印的虚拟机内部的类名称将会带一个‘*’前缀。如果指定了live子选项,则只计算活动的对象。

  • jmap -clstats pid。打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会打印。

  • jmap -finalizerinfo pid。打印等待终结的对象信息。Number of objects pending for finalization: 0说明没有等待终结的对象。

  • jamp -dump:live,format=b,file=./jmap.bin pid。以二进制格式转储java堆到指定路径下的filename文件中。指定了live子选项,则只会转储活动的对象。

在macOS上使用这个命令同样也会报错。但某些命令还是可以的,比如dump二进制文件。

1.5 jhat - JVM Heap Dump Browser

作用:与jmap搭配使用,用来分析jmap生成的堆转储文件。jhat内置了一个微型的www.yidunidc.com欢迎留下您的宝贵建议】

本文共计2437个文字,预计阅读时间需要10分钟。

有哪些JDK内置的性能分析工具可以使用?

有时会遇到服务器CPU过载或程序卡死等问题,这类bug通常定位困难。这类问题往往隐藏得比较深,且可能具有偶发性,比较棘手。对此类问题,我们通常有一套固定的分析流程。

有时候碰到服务器CPU飙升或者程序卡死之类的问题,一般都不太好定位。这类bug一般都隐藏的比较深并且还可能是偶发性的,比较棘手。

对于此类问题,一般我们都有固定的分析流程。借助于JDK自带的一些分析工具,比如jstack、jmap、jstat一类的命令行工具,除此之外,还有jconsole、mat、jvisualvm这些图形界面分析工具。

有哪些JDK内置的性能分析工具可以使用?

这篇文章基于JDK8,操作系统是macOS 12.0.1

1、一些命令行分析工具

这些命令行分析工具都在jdk/bin目录下

解压jdk/lib/tool.jar可以得到上述工具的class文件

1.1 jps - JVM Process Status Tool

作用:列出正在运行的虚拟机进程,并显示虚拟机执行主类名称以及这些进程的本地虚拟机唯一ID。

第一个参数说明:

  • -q:默认携带的参数,显示进程ID。

  • -m:显示进程ID,主类名称,以及传入main方法的参数。

  • -l:显示进程ID,主类全名。

  • -v:显示进程ID,主类名称,以及传入JVM的参数。

  • -V:显示进程ID,主类名称。

[-mlvV]可以任意组合使用。

第二个参数说明:

  • hostid:服务器的ip地址。不指定的情况下,默认为当前服务器。如果要查看其他机器上的JVM进程,需要在待查看机器上启动jstatd。
1.2 jstat - JVM Statistics Monitoring Tool

作用:监视虚拟机各种运行状态信息,可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

命令格式:jstat -

参数说明

第一个参数:option,代表用户希望查询的虚拟机信息,主要分为3类:类装载、垃圾收集和运行期编译情况。具体选项如下:

  • -class:显示有关类加载器行为的统计信息。

  • -compiler:显示有关java hotspot vm即时编译器行为的统计信息。

  • -gc:显示有关垃圾收集堆行为的统计信息。

  • -gccapacity:显示有关各个垃圾回收代容量及其相应容量的统计信息。

  • -gccause:显示有关垃圾收集统计信息(同-gcutil),以及上一次和当前垃圾收集事件的原因。

  • -gcnew:显示新生代行为的统计信息。

  • -gcnewcapacity:显示有关新生代大小及其相应空间的统计信息。

  • -gcold:显示老年代行为的统计信息和元空间统计信息。

  • -gcoldcapacity:显示有关老年代大小的统计信息。

  • -gcmetacapacity:显示有关元空间大小的统计信息。

  • -gcutil:显示有关垃圾收集统计信息。

  • -printcompilation:显示java hotspot vm编译方法统计信息。

第二个参数:vmid。如果是本地虚拟机进程,那么vmid和本地虚拟机唯一ID是一致的。如果是远程虚拟机进程,那么vmid的格式是:protocol:lvmid[@hostname[:port]/servername]

第三个参数:interval。采样间隔,单位为s或ms,默认单位是ms,必须为整数。指定该参数,jstat命令将在每个间隔产生输出。

第四个参数:count。要显示的样本数。

import java.io.IOException; /** * -class: * Loaded:已加载的类数量。 * Bytes:已加载的kb数。 * Unloaded:卸载的类数量。 * Bytes:卸载的kb数。 * Time:执行类加载和卸载的耗时。 * * -compiler: * Compiled:执行的编译任务数。 * Failed:编译失败的任务数。 * Invalid:无效的编译任务数。 * Time:执行编译任务所花费的时间。 * FailedType:失败的编译类型。 * FailedMethod:失败的编译类名和方法。 */ public class Demo1_jstat { public static void main(String[] args) throws IOException { System.out.println("jstat"); System.in.read(); } }

启动上面的demo后

import java.io.IOException; /** * -gc: 垃圾收集的堆统计信息 * S0C:s0区的容量(kb) * S1C:s1区的容量(kb) * S0U:s0区的使用大小(kb) * S1U:s1区的使用大学(kb) * EC:eden区的容量(kb) * EU:eden区的使用大小(kb) * OC:老年代容量(kb) * OU:老年代的使用大小(kb) * MC:元空间的容量(kb) * MU:元空间的使用大小(kb) * CCSC:压缩的类空间容量(kb) * CCSU:使用的压缩类空间大小(kb) * YGC:新生代垃圾收集次数 * YGCT:新生代垃圾回收时间 * FGC:full gc收集次数 * FGCT:full gc垃圾回收时间 * GCT:总垃圾收集时间 * * -gcutil:垃圾收集统计信息 * S0:s0区的使用率 * S1:s1区的使用率 * E:eden区使用率 * O:老年代使用率 * M:元空间使用率 * CCS:压缩类空间使用率 * YGC:新生代gc次数 * YGCT:新生代gc耗费时间 * FGC:full gc次数 * FGCT:full gc耗费时间 * GCT:总垃圾收集时间 */ public class Demo2_jstat { // -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc public static void main(String[] args) throws IOException { final int _1MB = 1024 * 1024; // 申请2M的空间 byte[] b1 = new byte[2 * _1MB]; System.out.println("1111"); System.in.read(); // 申请2M的空间 byte[] b2 = new byte[2 * _1MB]; System.out.println("2222"); System.in.read(); // 申请2M的空间 byte[] b3 = new byte[2 * _1MB]; System.out.println("3333"); System.in.read(); } }

启动上面的程序之前,先指定一些jvm参数

-Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc

然后启动demo

刚启动时,程序会申请2M的数组,可以看到eden区的使用率是62.37%,ygc的值为0。

让程序申请第二个2M的数组,之后再查看堆内存信息

可以发现eden区的使用率达到了87.37%。

让程序申请第三个2M的数组,发现控制台输出提示

再查看堆内存信息

发现eden区的使用率降到了26.71,s1区使用率时70.80%,老年代的使用率是40%即4096kb也就是4M空间大小。同时ygc的次数是1,说明进行了一次ygc,并且把大对象放进了老年代中。

1.3 jinfo - Configuration Info For Java

作用:实时的查看和调整虚拟机各项参数。

命令格式:jinfo [option]

参数说明

第一个参数:option。

  • no options:输出全部的参数和系统属性。

  • -flag name:输出对应名称的参数。

  • -flag [+ | -] name:开启或者关闭对应名称的参数。

  • -flag name=value:设置对于名称参数的参数值。

  • -flags:输出全部的参数。

  • -sysprops:输出全部的系统属性。

命令演示

  • jinfo pid

  • jinfo -flag PrintGCDetails pid (输出PrintGCDetails参数的值)

  • jinfo -flag +PrintGCDetails pid (开启PrintGCDetails参数)

  • jinfo -flag HeapDumpPath=/ pid (设置HeapDumpPath参数的值)

在我电脑上使用这个命令会报错,据说是macOS的一个bug,需要升级到jdk9,懒得升了。bug链接

1.4 jmap - Memory Map For Java

作用:一个多功能的命令,它可以生成Java程序的dump文件,也可以查看堆内对象的信息、classloader的信息和finalizer队列。

命令格式:jmap [option]

参数解释

第一个参数:option

  • no option:查看进程的内存镜像信息。

  • -heap:显示Java堆详细信息。

  • -histo[:live]:显示堆中对象的统计信息。

  • -clstats:打印类加载器信息。

  • -finalizerinfo:显示在F-Queue队列等待Finalizer线程执行finaizer方法的对象。

  • -dump::生成堆转储快照。

命令演示

  • jamp pid。打印出虚拟机加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。

  • jamp -heap pid。打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和各内存区域内存使用信息。

  • jmap -histo:live pid。显示堆中对象的统计信息,包括每个Java类型,对象数量,内存大小(单位字节),完全限定的类名。打印的虚拟机内部的类名称将会带一个‘*’前缀。如果指定了live子选项,则只计算活动的对象。

  • jmap -clstats pid。打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会打印。

  • jmap -finalizerinfo pid。打印等待终结的对象信息。Number of objects pending for finalization: 0说明没有等待终结的对象。

  • jamp -dump:live,format=b,file=./jmap.bin pid。以二进制格式转储java堆到指定路径下的filename文件中。指定了live子选项,则只会转储活动的对象。

在macOS上使用这个命令同样也会报错。但某些命令还是可以的,比如dump二进制文件。

1.5 jhat - JVM Heap Dump Browser

作用:与jmap搭配使用,用来分析jmap生成的堆转储文件。jhat内置了一个微型的www.yidunidc.com欢迎留下您的宝贵建议】