如何读懂 JIT 编译日志,判断热点方法是否被内联优化

解读

在国内互联网公司的性能测试面试里,这道题常被用来区分“只会跑脚本”与“能看懂 JVM 行为”的候选人。面试官想确认三件事:

  1. 你是否真的在生产环境打开过-XX:+PrintCompilation、-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining 等诊断日志;
  2. 你能否把日志片段翻译成“方法-字节码-机器码-内联决策”这一完整链路;
  3. 你能否根据内联失败原因,反向给开发提出可落地的优化建议(减少虚方法、调整继承层次、加 final、减小方法体等)。
    回答时务必用真实日志行举例,避免只背概念;同时要给出“一看就懂”的排查套路,体现性能测试工程师“把黑盒变成白盒”的价值。

知识点

  1. 开启日志的常用组合(JDK8~JDK17通用,生产可动态打开):
    -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining -XX:+PrintAssembly 可选
    日志级别:info 会输出到 stdout,需配合 GREP/AWK 截取。
  2. 日志行核心字段:
    timestamp compilation_id level tier method@@OSR_BCI size deopt 状态 〈inline_result〉
    其中 tier 0~4 对应 C1/C2 编译;inline_result 只有加 PrintInlining 才出现。
  3. 内联成功标志:
    @ 〈callee〉 inline (hot) 或 inline (profitable)
  4. 内联失败高频原因:
    • too big(字节码>默认35字节,-XX:MaxInlineSize)
    • virtual call(虚方法未做CHA 证明单态)
    • recursive(递归深度>默认9层)
    • profile is unstable(调用点类型profile 变化剧烈)
  5. 性能测试侧常用量化指标:
    一次压测周期内,热点方法被采样次数>1% 却未内联,可预期多一次虚方法开销≈510 ns;在10w QPS 场景下,约增加0.51 ms RT,可直接换算成SLA 违约风险。
  6. 安全点与日志开销:
    打开PrintAssembly 会生成.so 并引入safepoint 延迟,生产必须间歇性采样,不可一直开。

答案

示例日志(已脱敏):

29.123  1234  3       java.lang.String::hashCode (60 bytes)   inline (hot)
29.124  1235  4       com.xxx.OrderService::calcDiscount (35 bytes)   virtual call  too big

判断步骤:

  1. 先找“compilation_id”与“tier”:1234 号任务由C2 编译(tier 3),说明已是热点;
  2. 看同一行尾部:hashCode 显示 inline (hot),证明被内联;calcDiscount 显示 virtual call + too big,说明内联失败;
  3. 若需进一步确认,把-XX:MaxInlineSize=50 临时调大,重新压测,观察calcDiscount 行是否变为 inline,同时对比99rt 是否下降;
  4. 如果调大后仍提示“virtual call”,则需在代码侧把calcDiscount 改为final 或采用内联缓存技巧,再回归验证。
    面试现场可把上述四步口语化:“先抓日志关键字,再看tier 和inline 标记,接着用JVM 参数做对比实验,最后把结论量化成RT 收益反馈给开发。” 这样既有工具细节,也有性能测试的闭环思维。

拓展思考

  1. 在容器化、微服务场景下,同一Pod 多次发布导致Code Cache 被刷掉,热点方法需重新编译,内联状态可能翻转。性能测试可监控“code_cache_full” JMX 指标,配合发布窗口做回归,防止“昨天达标、今天掉链子”。
  2. 对于使用GraalVM Native Image 的项目,传统JIT 日志消失,需要转用“-H:+PrintAnalysisStatistics” 和“-H:InlineBeforeAnalysis”,面试可主动提及“编译期内联”与“运行期内联”差异,体现技术宽度。
  3. 高并发银行系统常把-XX:+UseStringDeduplication 与内联一起调优,性能测试可设计“百万级String 拼接”场景,验证内联后是否触发更多GC 优化,形成“编译器—GC—RT”三维报告,直接对标金融SLA。