JVM工具实战:线上问题排查与性能分析


在程序运行过程中,我们可能会遇到各种问题,而稳定性风险是我们无法回避的一个话题。由于代码质量不佳或架构设计上的缺陷,JVM 层面的风险主要表现为内存溢出和死锁等问题,常见的异常包括 OOM 和 CPU 使用率急剧上升。为了深入了解问题的根本原因,我们需要熟练掌握 JVM 工具的使用。幸运的是,JVM 已经为我们提供了一系列的诊断工具。今天,我会带你熟悉 JVM 的一些常见诊断工具。

jps:java 进程获取

命令:

jps [option]
选项作用
-q只输出进程ID
-m输出启动 java 程序传入main函数的值
-l输出执行的jar包的全路径
-v输出执行的java程序的JVM参数

如:

# jps -l
1215122 /data/webapp/api.jar
1227025 /data/webapp/admin.jar
3104812 /data/webapp/bm-platform-admin-server.jar

jstat:虚拟机统计信息监视工具

命令:

jstat option pid [执行频率] [执行次数]

如:

# jstat -gcutil 1454721 1000 3
S0     S1     E      O      M     CCS    YGC     YGCT     FGC    FGCT     CGC    CGCT       GCT   
0.00  95.88  49.36  73.90  99.31  97.27     43     0.243     0     0.000    10     0.014     0.257
0.00  95.88  49.36  73.90  99.31  97.27     43     0.243     0     0.000    10     0.014     0.257
0.00  95.88  49.36  73.90  99.31  97.27     43     0.243     0     0.000    10     0.014     0.257

查看垃圾回收,进程ID:1454721,执行频率:1s,执行次数:3次。

我们再来了解一下查询出的这几个参数的含义:

  • S0、S1:Survivor0、Survivor1 幸存者区
  • E:新生代区
  • O:老年区
  • P:永久代
  • YGC:MinorGC
  • YGCT:MinorGC 的耗时
  • FGC:FullGC
  • FGCT:FullGC 总耗时
  • GCT:GCTime,意思是 GC 总耗时

下面的列表是 jstat 一些选项的作用,你可以自己在服务上敲一下命令试试。

选项作用
-class监视类装载、卸载总量、总空间及类装载所耗费的时间
-gc监视垃圾回收信息
-gcuilt与 -gc 功能类似,输出垃圾回收百分比
-gcnew监视新生代垃圾回收信息
-gcold监视老年代垃圾回收信息

jinfo:java 配置信息工具

jinfo命令可以用来查看和调整 JVM 的配置参数。使用 jps 的-v选项可以查看 JVM 启动时显式指定的参数,而 jinfo 的-flag选项可以帮助我们查看那些使用了默认值的参数。更强大的是,jinfo 甚至可以在运行时修改这些参数。jinfo 的命令格式如下:

命令:

jinfo pid

如:

jinfo 1454721

jmap:java 内存映像工具

用于创建 Java 堆内存的快照,也就是我们常说的"dump 文件",生成的 dump 文件对于分析内存溢出问题非常有用。jmap 不仅可以获取 dump 文件,还可以查询永久代、堆空间的使用情况和垃圾收集器的信息。jmap 的命令格式如下:

jmap [option] pid

选项如下:

选项作用
-dump生成java堆转储快照。格式为:-dump:[live,]format=b,file=filename.bin。其中live子参数说明是否只dump出存活的对象
-heap显示java堆详细信息,如使用哪种回收器、参数配置、分带状况等
histo显示堆中对象统计信息,包括类、示例数量、合计容量

使用示例:

jmap -dump:format=b,file=aaa.bin 1454721

jstack:Java 堆栈跟踪工具

jstack 用于生成虚拟机当前时刻的线程快照,也就是“线程 dump”文件。线程快照的意思就是线程当前的堆栈信息,生成线程快照的主要目的通常是为了定位线程阻塞的原因,如死循环、死锁、IO 资源问题等。如果发生线程阻塞,我们可以使用 jstack 来查看线程堆栈,就可以清晰地看到这些线程在后台执行什么任务、wait 什么 IO 资源。

我们来看一下 jstack 的命令格式:

jstack [option] pid

我们使用 jstack -l 14545 查看线程堆栈。

"log-producer-pool-4" #1610 prio=5 os_prio=0 cpu=4.41ms elapsed=99773.42s tid=0x00007f2b94030080 nid=0x32da0c waiting on condition  [0x00007f2b6e0df000]
   java.lang.Thread.State: WAITING (parking)
        at jdk.internal.misc.Unsafe.park(java.base@17.0.11/Native Method)
        - parking to wait for  <0x00000000f5385d90> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(java.base@17.0.11/LockSupport.java:341)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(java.base@17.0.11/AbstractQueuedSynchronizer.java:506)
        at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@17.0.11/ForkJoinPool.java:3465)
        at java.util.concurrent.ForkJoinPool.managedBlock(java.base@17.0.11/ForkJoinPool.java:3436)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@17.0.11/AbstractQueuedSynchronizer.java:1623)
        at java.util.concurrent.LinkedBlockingQueue.take(java.base@17.0.11/LinkedBlockingQueue.java:435)
        at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@17.0.11/ThreadPoolExecutor.java:1062)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.11/ThreadPoolExecutor.java:1122)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.11/ThreadPoolExecutor.java:635)
        at java.lang.Thread.run(java.base@17.0.11/Thread.java:842)

jstack选项如下:

选项作用
-F当正常输出的请求不被响应时,强制输出线程堆栈
-l除堆栈外,显示相关锁的信息
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值