JDK Flight Recorder (JFR) 是一种结构化日志记录工具,用于记录广泛的系统级事件。类似于飞机黑匣子持续记录飞行数据以供事故调查使用,JFR 持续记录 JVM 中的事件流 (stream),以便用于诊断问题。这种方法的优势在于它能按时间顺序捕获事故发生前系统的详细信息。JFR 旨在将对性能的影响降至最低,并且可以安全地在生产环境中长期运行。
从 Java 17 开始,JFR 也是 JProfiler 的数据源之一。除了使用 JVM profiling 接口的 Native Agent 之外,JVM 中还有一些在 profiling 上下文中值得关注的高级系统。一个是为 JProfiler 中的某些遥测 (telemetry) 提供数据的 MBean 系统,另一个则是用于垃圾回收器探针 (probe)的 JFR。为此,您无需直接与 JFR 交互,JProfiler 会透明地处理 JFR 事件流 (stream)。
JFR 在 JProfiler 中的集成
JProfiler 完全集成了 JFR 记录,因此您可以轻松地从本地机器或未配置 JFR 记录的远程机器上运行的 JVM 中捕获数据。
当您在 JProfiler UI 中打开 JFR 快照时,可用的视图 (view) 和部分与常规 profiling 会话 (session) 不同。UI 的核心是事件浏览器。适用于 JFR 的所有其他视图 (view) 均在单独的章节中进行了说明。
当您处理事件类型、设置过滤器并查看分析时,JProfiler 偶尔需要重新扫描 JFR 快照文件。JFR 快照文件可能非常庞大,将所有数据保留在内存中或预先计算所有分析是不切实际的。因此,不建议从网络驱动器打开 JFR 快照。
打开极大的 JFR 快照时,您可以通过在文件选择器中选中“自定义分析”复选框,并排除分析不需要的事件类别,从而加快快照处理速度并减少内存占用。可用的事件类别涵盖单个探针 (probe) 和视图部分。CPU 视图 (view)、内存视图以及遥测 (telemetry) 视图的事件类型是不可选的,必须加载。
例如,如果您仅对 CPU 数据感兴趣,可以排除所有探针 (probe) 和事件浏览器。JProfiler 致力于成为最快的 JFR 查看器,并能快速打开典型的 JFR 快照,但 JFR 记录潜在地没有大小限制,您可能会遇到几十 GB 大小的快照,此时打开速度可能会成为一个问题。
JFR 快照中的堆栈跟踪
JFR 的一个重要特性是能够以高效的方式记录特定事件类型的完整堆栈跟踪。对于此类事件类型,您可以在 JFR 设置中切换堆栈跟踪记录。许多 JVM 应用程序事件类型(尤其是与线程相关的事件类型)默认启用了堆栈跟踪记录。
JFR 仅收集固定深度以内的堆栈跟踪,因此过长的堆栈跟踪会被截断。被截断的跟踪不适合用于构建易于理解的调用树 (call tree),因此这些跟踪会显示在带有特殊标记的节点下方。使用
-XX:FlightRecorderOptions=stackdepth=<nnnn>
VM 参数,您可以增加 JFR 中收集的跟踪深度,从而消除应用程序中的截断跟踪。