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

为什么同JVM下第二次启动JFR录制会丢失自定义事件的部分字段?

问题根因

该问题是OpenJDK 11、16版本中JFR处理自定义事件动态字符串字段的已知缺陷:
第一次JFR录制结束后,JVM会为自定义事件的字段访问生成JIT优化快速路径,对于运行时动态生成的未入池字符串(你代码中span.name()返回值、字符串拼接得到的eventName2都属于这类),第二次录制启动时JFR不会自动将这些动态字符串注册到新录制的字符串常量池中。而字面量常量字符串(比如eventName3赋值的"test-test-test"在类加载时就已经进入全局字符串池)、基础类型字段(比如long类型的timestamp)不受该逻辑影响,所以可以正常显示。

修复方案

可任选以下一种方案解决:

  1. 对动态赋值的字符串字段主动调用intern()方法,让动态字符串进入全局常量池,修改后的事件赋值代码如下:
QueryJfrEvent qevent= new QueryJfrEvent();
if(qevent.isEnabled()){
    String name = span.name().intern(); // 主动入池
    System.out.println(" Check ---- " + name);
    
    qevent.eventName = name;
    qevent.eventName2 = (name + "-bla-bla-bla").intern(); // 拼接后主动入池
    qevent.eventName3 = "test-test-test";
    qevent.timestamp = span.startTimestamp();
    qevent.commit(); // 注意原代码此处漏写方法括号,属于笔误
}
  1. 修改你使用的test.jfc配置文件,为trace.dbquery事件显式开启字符串池持久化配置,找到配置中对应自定义事件的段落,添加如下配置项:
<event name="trace.dbquery">
  <setting name="enabled">true</setting>
  <setting name="stackTrace">true</setting>
  <setting name="stringPool">true</setting> <!-- 强制开启该事件的动态字符串池录制 -->
</event>
  1. 升级JDK版本到17及以上,该问题在JDK 17正式版中已经被修复,无需修改任何业务代码即可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 20:21:01