几个必会的JDK性能监控和故障处理工具

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

bcb475ee848e5b94ca7f8ed7de2123d8.gif

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、ERP、CRMAI 大模型等等功能:

  • Boot 多模块架构:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • Cloud 微服务架构:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 双版本 

来源:江南一点雨

810b57b2dcb880ecb83f04639206b2bd.jpeg


虽然阿里巴巴的 Arthas 这个工具很强大,不过如果你能够熟练使用 JDK 提供的工具,那么在不借助任何外力的情况下,就可以非常轻松的进行应用的性能监控和故障处理。

JDK 提供的工具,大家最熟悉的估计就是 java 和 javac 这两个了,然而 JDK 实际上提供了非常强大的性能监控和调试工具,今天松哥就来和大家一起捋一捋这些工具。

一 jps

这个应该是大家最为熟悉的工具了,使用这个命令可以快速列出来系统上正在运行的 Java 进程。

这个命令在执行的时候一般有四个参数:

  • -q 表示只输出进程 ID,不输出主类名称,准确来说,这里输出的叫做本地虚拟机进程 ID(LVMID),不过对于本地虚拟机进程来说,LVMID 和操作系统的进程 ID 是一致的。

  • -l 表示输出主类的全名,如果进程执行的是 jar 包,那么就输出 jar 包的完整路径。

  • -m 表示输出进程启动时传递给 main() 函数的参数。

  • -v 表示输出进程启动时的 JVM 参数。

0926966431c2a4637121d9a013a56c98.png

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

二 jstat

jstat 是用来监控虚拟机各种运行状态信息的命令行工具,这个工具可以用来查看本地或者远程虚拟机内存、垃圾收集、即时编译等等信息。

一般来说,这些数据我们可以借助可视化工具来查看,例如 JMC 或者 VisualVM 等等,但是有时候在服务器环境下,在命令行环境下没法运行 GUI 图形界面,那么此时 jstat 是一个不错的选择。

jstat 运行参数比较多,松哥这里列举几个比较常见的参数:

  • -class 这个表示监视类加载、卸载数量、总空间以及类装载所耗费的时间。

8e0ef810dbfa310d67cea9ee6a9806cc.png
  • -gc 这个表示监视 Java 堆状况,包括 Eden 区,两个 Survivor 区、老年代以及永久带的容量,已使用的空间以及垃圾收集时间合计等等信息。

6304d314b2d36fbb0e32ba781307a3ea.png

命令中的 1s 8 表示每秒打印一次,一共打印 8 次,如果不设置,则打印一次。

这里输出的各参数含义如下:

S0C:Survivor0 的容量。S1C:Survivor1 的容量。S0U:Survivor0 已使用大小。S1U:Survivor1 已使用大小。EC:Eden 区容量。EU:Eden 区已使用大小。OC:老年代容量。OU:老年代已使用大小。MC:元数据区容量。MU:元数据区已使用大小。CCSC:压缩类空间容量。CCSU:压缩类空间已使用大小。YGC:年轻代垃圾回收次数。YGCT:年轻代垃圾回收总耗时。FGC:FullGC 次数。FGCT:FullGC 总耗时。CGC:GC STW 的次数。CGCT:GC STW 的时间。GCT:总 GC 时间。

基本上我们想知道的关于 JVM 运行内存状态的信息,这里都有了。

  • -gccapacity 这个监控内容与 -gc 类似,不过输出内容主要关注 Java 堆各个区域使用到的最大最小空间。

bacf8ffad7b10a1da284778b7b282824.png

这里涉及到的参数我也和大家稍微解释下:

NGCMN:新生代最小容量。NGCMX:新生代最大容量。NGC:新生代当前容量。OGCMN:老年代最小容量。OGCMX:老年代最大容量。OGC:老年代当前容量。MCMN:元空间最小容量。MCMX:元空间最大容量。CCSMN:压缩类空间最小容量。CCSMX:压缩类空间最大容量。CCSC:压缩类空间当前容量。

补充输出内容和前面一致的我就不重复解释了。

  • -gcutil 这个和 -gc 类似,不过输出的内容主要关注已使用的空间占总空间的比例。

858b75c62bb40f047780acf547df06df.png

S0:Survivor0 区使用比例。S1:Survivor1 区使用比例。E:Eden 区使用比例。O:老年代使用比例。M:元空间使用比例。CCS:压缩类空间使用比例。

这块能加的参数实际上非常多,对于我们来说比较常用的主要就是上面这几个命令。

如果小伙伴们想要查看完整指令,可以参考官方文档:https://docs.oracle.com/en/java/javase/11/tools/jstat.html

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

三 jinfo

jinfo 命令可以实时查看和修改 JVM 各项参数。

能修改这就很牛了。

平时我们启动一个 Java 项目,一旦启动之后,如果想要知道项目启动时的各项 JVM 参数,那么就只能去查文档了。但是如果你能够熟练使用 jinfo,那么这个事情就容易很多了。

a2eeb75326c05222788a506dc9ea8b25.png

直接 jinfo pid 就会展示出来所有的 JVM 参数。

如果只想查看某一个 JVM 参数,那么可以使用如下命令:

jinfo -flag CICompilerCount 28893
3d80d1c3edb02f15bc1626e3c3f872cd.png

也可以在不重启 JVM 参数的情况下,动态修改 JVM 参数。

例如松哥这里的案例,原本是没有开启 PrintClassHistogram 的,我现在动态开启:

8110f571d9adaa081cdd5e5e3b8b0311.png

PrintClassHistogram 前面没有符号,表示查看当前状态;PrintClassHistogram 前面有个 + 表示开启;PrintClassHistogram 前面有个 - 表示关闭。

这种方式是修改 value 为 boolean 的 JVM 参数,如果是 key-value 格式的 JVM 参数,那么可以按照下面这种方式修改:

c185798979eec923a0d5608bb6d9a819.png

当然这个修改并非所有的 JVM 参数都能改,至于哪些 JVM 参数能改,我们可以执行 java -XX:+PrintFlagsInitial 命令,找到标记为 manageable 的参数,这些参数是可以动态修改的。

b6a304ddcb39550b826fa7bffba77995.png

另外我们在代码中通过 System.getProperties() 获取到的属性,也可以通过指令打印出来:

jinfo -sysprops 57002
96396eb182b8e2c18aa788265cadac3c.png

四 jmap

jmap 命令一般可以用来生成 heapdump。

这个命令在新版本 JDK 中运行的时候,前面要加上 jhsdb。

c4ba04f6f873350acc69727fbf94412b.png

从这里我们可以解读出哪些信息呢?

  • 可以看到最大可分配的 Heap 大小(MaxHeapSize)

  • 可以看到 JVM 启动时分配的新生代内存(NewSize)

  • 可以看到可分配的最大新生代内存(MaxNewSize)

  • 可以看到 JVM 启动时分配的老年代大小(OldSize)

  • 可以看到老年代和新生代的内存比例(NewRatio),上面截图中表示 老/新=2,即老年代占 2/3,新生代占 1/3。

  • 可以看到新生代中 Eden 区和一个 Survivor 区的比例(SurvivoRatio)

  • 可以看到初始的 Metaspace 大小(MetaspaceSize)

  • 可以看到最大的 Metaspace 大小(MaxMetaspaceSize)

  • 可以看到在 G1 收集器下,每个 Region 的大小(G1HeapRegionSize)

下面的这些就好理解了,分别是不同区域的 regions 数量、总空间、使用空间以及空闲空间。

也可以利用 jmap 查看 Heap 中对象的统计信息,比如对象的数量、占用内存的大小以及类的完整路径。

jmap -histo:live pid

加上 :live 表示查看活着的对象信息。

f38359b228b2fc5c8ab07a053f2b9fca.png

也可以查看 Heap 中元空间的类加载信息 jmap -clstats 28893

a8443e8055ed689e97e3132ee40b1f0d.png

这里可以看到有哪些类加载器,分别加载了哪些类。

当然,最重要的功能是生成 dump 文件了:

f27c89174cd62e88561555efa8821477.png

这里几个参数说明一下:

  • live 表示只转存堆中活动对象,如果没有制定,则存所有对象。

  • format=b 表示以 hprof 二进制格式转存。

  • file=xxx 表示生成的文件名。

生成的文件,可以使用 idea 打开查看。

小技巧:获取 heapdump 还有哪些方式?

  1. 使用 kill -3 吓一吓 JVM,就能拿到堆转储快照。

  2. -XX:HeapDumpOnOutOfMemoryError 参数可以让虚拟机在内存溢出时自动生成堆转储快照。

五 jhat

这个工具目前已经废弃了。

松哥这里就简单说下这个工具的作用以及替代品。

前面 jmap 会生成 heapdump 文件,这是一个二进制文件,那么我们通过什么工具去分析这个文件呢?比如可以使用 Eclipse 的 MAT,当然现在 IDEA 也可以直接打开这个文件分析,这块成熟的工具还是非常多的。

那么 jhat 其实也是一个这样的工具,jhat 内置了一个微型的 Web 服务器,让开发者可以在浏览器中查看相关数据。但是因为 jhat 功能比较简陋,所以目前已经废弃了。

六 jstack

jstack 可以查看 JVM 当前时刻的线程快照。

如果某个线程执行比较耗时,或者发生死锁,发生死循环等,那么就可以通过这个指令来查看各个线程的调用堆栈,检查到底发生了什么问题。

9beb2bb4d9ba2ca115f586992d4e0183.png

-l 表示出了堆栈之外,也把锁的相关信息显示出来。

不过这个命令松哥并不常用。因为 Thread 中有一个 getAllStackTraces 方法,我们通过 jstack 命令获取到的信息基本上通过这个方法都能获取到,所以可以自己结合这个方法写监控页面查看相关信息。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

6a97d10eb98cb5be1cd2702676a36968.png

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

b295f27512a7040b9a4de3cec27a93ab.png

46bbc5ed62ad80ba394336e63857528e.png191ddf6d84da06005d6af9f2d7c03613.png1f1c61bb0d34393d3083edb481bc7ec7.png9d808aaffa8caaa12ea82193762b8400.png

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值