JVM热点探测只识别高频执行的方法和循环体,不存在“高频变量方法”概念;它通过方法调用计数器(默认10000次)和回边计数器(默认约100000次)分别触发C1/C2编译,变量本身不参与热点判定。

热点探测不识别“高频变量方法”,这个说法本身存在概念混淆。JVM的热点探测机制针对的是执行频率高的代码段,而非变量或“变量方法”这类不存在的术语。它识别的是两类明确的热点代码:被频繁调用的方法,以及被频繁执行的循环体(即回边热点)。
方法调用计数器:盯住“谁被叫得多”
每个方法都有一个独立的调用计数器,每次该方法被调用时加1。默认阈值为10000次(分层编译下实际生效值可能浮动)。达到阈值后,JVM将该方法提交给C1编译器进行初次编译;若持续高频,还可能升级至C2深度优化。
- 计数器只统计“进入方法”的次数,不关心内部变量变化
- 静态方法、实例方法、构造器都适用同一套计数逻辑
- 可通过-XX:CompileThreshold=5000降低阈值,便于测试观察,但生产环境不建议随意调整
回边计数器:专盯“循环里反复跳的那一下”
回边(back edge)指循环末尾跳转回循环开头的动作,比如for末尾的条件判断跳转、while再次检查条件时的跳转。每次发生这种跳转,对应循环体的回边计数器就加1。默认阈值通常是方法调用计数器的10倍(约100000次)。
- 即使整个方法只被调用几次,只要某个
for循环执行了上万次,也会触发OSR编译 - 编译对象仍是整个方法,但入口点会定位到循环头对应的字节码位置(BCI)
- 可用-XX:+PrintCompilation看到带osr标记的编译日志,确认是否发生栈上替换
没有“高频变量方法”,只有高频执行路径
JVM不跟踪变量访问频次,也不为某个变量单独编译方法。所谓“变量相关热点”,实际是变量所处的代码路径高频执行的结果。例如:
- 一个局部变量在循环内反复读写——触发的是回边计数器
- 一个getter方法被界面反复调用——触发的是方法调用计数器
- 变量本身不会让方法变“热”,执行动作的密度才会
验证与调试的关键手段
想确认热点是否被正确识别,不能靠猜测,得靠输出和参数配合:
- 启动时加上-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintTieredEvents
- 观察日志中是否出现目标方法名、编译级别(1=C1,4=C2)、是否含osr
- 避免依赖采样式探测(如VisualVM的CPU Profiler),它反映的是瞬时栈顶,不是JIT决策依据











