You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取运行中JVM的闲置监视器数量?排查GC停顿问题

JVM监视器数量获取与GC Safepoint Sync阶段耗时排查

一、JDK-8153224中获取当前监视器数量的方式

该案例里是通过HotSpot的诊断工具和内部接口获取的,具体两种常用方式:

  • 用jcmd <进程ID> GC.class_histogram命令,统计所有java.lang.Object的实例总数——因为每个Java对象都关联着一个监视器结构(即使没被加锁),这个数值可以近似当前JVM的总监视器数量。
  • 借助HotSpot的JVMTI(Java虚拟机工具接口)编写自定义工具,遍历JVM内所有对象,直接统计关联的监视器结构数量,这种方式更精准。

二、获取闲置监视器数量的方法

闲置监视器指未被任何线程持有的监视器,目前没有现成的JDK命令直接输出,可通过以下方式估算或统计:

  • 总监视器数减去被持有监视器数:先用上面的方法拿到总监视器数,再用jcmd <进程ID> Thread.print -l或jstack <进程ID>解析输出,统计线程当前持有的监视器数量(找输出里locked <0x...>这类锁持有记录),两者相减得到闲置监视器的近似值。
  • 自定义JVMTI工具统计:编写JVMTI代理程序,遍历所有对象并检查对象头的锁状态——处于无锁或偏向锁(无竞争)状态的对象,其对应的监视器属于闲置状态,直接统计这类对象的数量即可。

三、GC Safepoint "sync"阶段耗时过长的排查方向

结合你遇到的情况,sync阶段耗时久通常和线程进入safepoint的阻塞、JVM同步逻辑开销有关,可从这些角度排查:

  • 验证闲置监视器的影响:如果统计后发现闲置监视器数量极大,JVM在safepoint同步时可能需要遍历大量监视器状态,增加了同步开销,可尝试优化锁使用减少监视器数量。
  • 排查线程锁持有情况:用jstack或jcmd Thread.print查看线程栈,找出长时间持有锁的线程——这类线程会拖慢其他线程进入safepoint的速度,进而拉长sync阶段时间。
  • 调整JVM参数定位与优化:
    • 开启详细safepoint日志:添加-XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1,查看每个线程在safepoint阶段的耗时分布,精准定位拖慢sync的线程。
    • 调整偏向锁参数:若偏向锁是诱因,可尝试关闭偏向锁(-XX:-UseBiasedLocking),观察safepoint时间变化。
    • 设置safepoint超时:添加-XX:SafepointTimeout=5000 -XX:SafepointTimeoutDelay=1000,超时后JVM会打印拖慢safepoint的线程信息。
  • 代码层面优化:检查业务代码是否存在大量不必要的锁使用,比如对频繁创建的临时对象加锁、锁粒度太粗等情况,这类问题会导致监视器数量激增,加重JVM同步负担。

内容的提问来源于stack exchange,提问作者Morten Knudsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 22:25:21