JFR性能分析中ExecutionSample与ThreadDump选型及线程过滤问题
JFR 事件采集相关问题解答
1. 同频率采集 ExecutionSample 与 ThreadDump 事件的适用场景对比
两种方案的选型完全取决于你的分析场景和性能容忍度,核心差异如下:
- 性能开销差距极大:ExecutionSample 是JVM内置的非安全点采样事件,默认仅采集处于RUNNABLE状态的线程栈,单样本开销仅几纳秒,哪怕10ms间隔长期开启也不会对业务产生可观测影响;而同频率的 ThreadDump 需要触发全局安全点,必须等所有业务线程进入暂停状态后才能遍历全量线程栈,哪怕间隔设为100ms,也会导致明显的业务毛刺,开销是ExecutionSample的百倍以上。
- 数据可信度不同:ExecutionSample的采样时间点严格对齐调度时钟,不会受安全点等待影响出现偏差,甚至可以自定义配置采集WAITING、BLOCKED等非运行态的线程栈;ThreadDump的实际采集时间取决于所有线程到达安全点的时间,采集到的栈并不是预设间隔的即时栈,很容易出现「安全点偏移」导致的分析误差。
- 选型建议:
- 常规CPU热点排查、线上长期性能监控、低延迟业务性能分析:优先选择 ExecutionSample,无侵入、开销极低、数据可信度高
- 偶发死锁排查、全线程状态快照分析、锁竞争根因定位:仅在这类场景下使用ThreadDump,建议将采集间隔拉到秒级以上,尽可能降低对业务的影响
2. 是否支持仅采集指定线程的对应事件
ExecutionSample 支持按线程过滤
JDK 11及以上版本的原生JFR,以及JDK 8的商业版JFR,均支持通过自定义.jfc配置文件或者编程API设置线程过滤规则,仅采集你指定的线程ID/线程名称前缀的ExecutionSample事件,不需要采集全量线程数据。配置后可以通过jcmd命令动态启停、调整规则,无需重启目标JVM。
开源版JDK 8的JFR backport版本需要确认对应补丁是否支持线程过滤特性,大部分主流发行版的JDK 8已经适配该能力。
ThreadDump 不支持按线程过滤
ThreadDump事件的底层实现逻辑是全局安全点+全线程栈遍历,JVM目前没有提供指定线程范围的ThreadDump采集能力。如果你仅需要指定线程的栈快照,可以自定义JFR事件,在事件逻辑中调用Thread.getAllStackTraces()后自行过滤目标线程栈,但这种方案同样会产生全线程栈遍历的开销,不建议高频调用。
内容的提问来源于stack exchange,提问作者Benzion
相关产品推荐
相关产品推荐

