[转帖]【技术剖析】3. Java Flight Recorder - 事件机制详解

技术,剖析,java,flight,recorder,事件,机制,详解 · 浏览次数 : 0

小编点评

**JFR 的事件机制** **事件的生命周期** 1. **事件创建**: Java 线程创建并执行时会调用 `recordEvent` 方法记录事件。 2. **事件提交**: 提交事件到 `TLB` 中。 3. **事件被提交**: 在事件触发时,线程将其写入 `Global Buffer` 中。 4. **事件写入磁盘**: 当 `Global Buffer` 中的事件满流时,将其写入磁盘。 **事件的结构** 每个事件由以下部分组成: * **时间戳**: 记录事件发生的时间。 * **事件名称**: 记录事件类型。 * **附加信息**: 包含线程 ID、类名、方法名等信息。 * **数据**: 包含运行参数、堆栈信息等。 **自定义事件** 可以通过继承 `JfrEvent` 类并实现 `commit` 方法实现自定义事件。 **其他** * JFR 是事件驱动的,线程通过无锁(Lock-free)设计记录事件。 * 事件会被缓存和重现运行以提高效率。 * 可以通过配置选项控制事件的格式(二进制或 JSON)。

正文

https://bbs.huaweicloud.com/forum/thread-144149-1-1.html

 

作者:冯世杰

编者按:Java Flight Recorder(简称为JFR)曾经是Oracle JDK商业版的附属组件,在JDK 11中被正式开始开源,后又被移植到JDK8中。JFR本身对运行期系统的侵入性很小,同时又能提供相对准确和丰富的运行期信息;合理使用该工具可以极大地提高工作效率。本文介绍JFR剖析的事件机制,希望能帮助大家从原理上理解JFR并正确使用JFR。

  1. 本篇文章中的源码大部分来自openjdk8u262
  2. 本文出发点是梳理 JFR 的事件机制, 侧重点在于理解而非应用
  3. 使用上可以不要太过拘泥细节,可以具体问题具体分析。

 

对于JFR我们有着怎样的预期

它是一个辅助分析工具,我们希望借助它,尽可能低开销地收集运行时数据,从而辅助对JVM可能存在的故障、性能瓶颈进行分析。

我们结合JFR的Goals来看:

  • 提供基于生成和消费数据作为事件的API
  • 提供缓存机制和二进制数据格式
  • 允许配置和过滤事件
  • 为OS、JVM、JDK库提供相应的事件

从中,我们能粗略地获取这些信息 :

  1. 事件以自描述的二进制形式(.jfr)被保存着
  2. 事件中包含了数据,事件 ≈ 数据
  3. .jfr 文件 => read by some Provided API => 重现运行时数据 [ => 可视化]

我们想尝试了解JFR的事件驱动机制,具体点就是回答几个问题:

一个事件何时产生/启动监控? 经历了怎样的路径? 如何被保存? 保存到哪里?

 

JFR是事件驱动的

本节主要是一些前置信息 (假如你有所了解,可以快速浏览或者跳过本节内容): JVM行为基本都是Event,如类加载对应着Class Load Event, 垃圾回收对应GC Event;Event 主要由 timestamp, event name, additional info, data 这几部分组成。Event 收集四类事件的信息:

  • Instant Event , 发生就收集(e.g. Thread Start ...)
  • Duration Event,持续收集一段时间(e.g. GC Event ...)
  • Timed Event , 收集超过指定时间的事件
  • Sample Event,按频率采样

以JFR的Class Load Event为例, 看看一个事件的结构。(共计 24 bytes)

<memory address> : 98 80 80 00 87 02 95 ae e4 b2 92 03 a2 f7 ae 9a 94 02 02 01 8d 11 00 00

  • Event Size : 98 80 80 00
  • Event ID : 87 02
  • TimeStamp : 95 ae e4 b2 92 03
  • Duration : a2 f7 ae 9a 94 02
  • Thread ID : 02
  • Stack trace ID : 01
  • PayLoad(记录的数据,fields 取决于各个 Event 类型):
    • 加载的类 : 8d 11
    • 定义类的 ClassLoader : 00
    • 初始化类的 ClassLoader : 00

多个线程都会产生Event,线程通过无锁(Lock-free)设计记录事件。线程将事件首先写入到 ThreadLocalBuffer(简称TLB),  TLB被填满后,将被转存到 Global buffer(circular),对于较旧的数据,可以通过配置,选择丢弃或者写入磁盘,以便连续保存历史记录。示意图如下所示:

注意:TLB、Global Buffer和磁盘文件中的事件记录不会相互备份,未及时转存的数据可能发生丢失,本文不会就这点展开阐述。

前置内容已经交代清楚,接着回到正轨。

 

一个事件的生命周期

以下是枯燥乏味的一堆代码,但是不得不看。

首先来看JFR的结构,如下图所示:

肉眼可见的一堆钩子,这些hook用于记录对应的触发事件。

我们简单地挑一个 Thread Start 的事件,关注一下它的整个被触发到被记录的过程。在线程创建并执行时会调用记录JFR事件,代码如下:

可见当一个新的Java线程被创建时,只要开启了JFR, 那么就会执行上述代码;

接着看一下 on_thread_start 干了什么:

在此,我们看到了一个事件EventThreadStart,并且在事件中设置信息后被提交。

在 JEP 328中有一个更为简单直接例子,如下:

1.png

无需太过关心其内容。

我们只需关注这个事件生成的结构:

这里的 EventType 定义于 jfrEventClass.hpp, 该文件是编译时生成的,简单贴一下生成逻辑,可以参考Makefile文件,如下 (同样无需在意太多细节):

回到主旋律,继续来看事件的结构和成员函数,如下:

其中最为重要的成员函数是 JfrEvent::commit 方法,用于提交事件,代码如下.

在函数中,最后一段代码, 也是核心所在,用于真正记录事件:

这下,就可以很容易地和第1节的内容对应上了,特别是其中的事件模型的图片:

 

小结

用户是否可以自定义一个JFR事件?注意点有哪些?

这里通过JEP 328里的例子(稍微有点改动),来展示如何自定义JFR事件。

通过编译后直接执行如下命令:

> java -XX:StartFlightRecording,filename=event.jfr Test

可以得到如下日志信息:

Started recording 1. No limit specified, using maxsize=250MB as default.

Use jcmd 57980 JFR.dump name=1 to copy recording data to file.

日志可以通过标准的API进行解析,下面通过一个简单代码解析上面生成的事件,代码如下:

编译运行

> java Viewer | less

可以得到如下结果。

相信此时你已经对JFR的事件机制有了个不错的感觉。

实际上JFR的使用一般配合JMC[1]使用,在JMC中通过页面可以得到统计信息,更有助于判断系统的运行情况。

后记

如果遇到相关技术问题(包括不限于毕昇JDK),可以在论坛求助,也可以进入官网查找所有相关资源(包括二进制下载、代码仓库、使用教学、安装、学习资料等)。毕昇JDK社区每双周周二举行技术例会,同时有一个技术交流群讨论GCC、LLVM、JDK和V8等相关编译技术,感兴趣的同学可以添加如下微信小助手,回复Compiler入群。

小助手.jpg

原文转载自 openEuler-Java Flight Recorder - 事件机制详解

与[转帖]【技术剖析】3. Java Flight Recorder - 事件机制详解相似的内容:

[转帖]【技术剖析】3. Java Flight Recorder - 事件机制详解

https://bbs.huaweicloud.com/forum/thread-144149-1-1.html 作者:冯世杰 编者按:Java Flight Recorder(简称为JFR)曾经是Oracle JDK商业版的附属组件,在JDK 11中被正式开始开源,后又被移植到JDK8中。JFR本

[转帖]【技术剖析】17. Native Memory Tracking 详解(3):追踪区域分析(二)

https://bbs.huaweicloud.com/forum/thread-0227103792775240073-1-1.html 应用性能调优 发表于 2022-11-14 15:19:36143查看 上篇文章 Native Memory Tracking 详解(2):追踪区域分析(一) 

[转帖]【技术剖析】15. Native Memory Tracking 详解(1):基础介绍

https://bbs.huaweicloud.com/forum/thread-0246998875346680043-1-1.html 0.引言 我们经常会好奇,我启动了一个 JVM,他到底会占据多大的内存?他的内存都消耗在哪里?为什么 JVM 使用的内存比我设置的 -Xmx 大这么多?我的内存

[转帖]【技术剖析】16. Native Memory Tracking 详解(2):追踪区域分析(一)

https://bbs.huaweicloud.com/forum/thread-0295101552606827089-1-1.html 上篇文章 Native Memory Tracking 详解(1):基础介绍 中,分享了如何使用NMT,以及NMT内存 & OS内存概念的差异性,本篇将介绍NM

[转帖]【技术剖析】18. Native Memory Tracking 详解(4):使用 NMT 协助排查内存问题案例

https://bbs.huaweicloud.com/forum/thread-0211103793043202049-1-1.html 其他 发表于 2022-11-14 15:38:571174查看 从前面几篇文章,我们了解了 NMT 的基础知识以及 NMT 追踪区域分析的相关内容,本篇文章将

[转帖]【技术剖析】8. 相同版本 JVM 和 Java 应用,在 x86 和AArch64 平台性能相差30%,何故?

https://bbs.huaweicloud.com/forum/thread-168532-1-1.html 作者: 吴言 > 编者按:目前许多公司同时使用 x86 和 AArch64 2 种主流的服务器。这两种环境的算力相当,内存相同的情况下:相同版本的 JVM 和 Java 应用,相同的 J

[转帖]【技术剖析】10. JVM 中不正确的类加载顺序导致应用运行异常问题分析

https://bbs.huaweicloud.com/forum/thread-169439-1-1.html 神Bug... 发表于 2021-11-15 10:36:113973查看 作者:程经纬、谢照昆 > 编者按:两位笔者分享了不同的案例,一个是因为 JDK 小版本升级后导致运行出错,最终

[转帖]【技术剖析】12. 毕昇 JDK 8 中 AppCDS 实现介绍

https://bbs.huaweicloud.com/forum/thread-169622-1-1.html 作者:伍家华 > 编者按:笔者通过在 Hive 的场景发现 AppCDS 技术存在的价值,然后分析了 AppCDS 的工作原理,并将 JDK 11 中的特性移植到毕昇 JDK 8,在移植

[转帖]【技术剖析】11. 使用jemalloc解决JVM内存泄露问题

https://bbs.huaweicloud.com/forum/thread-169523-1-1.html 作者:王坤 > 编者按:JVM 发生内存泄漏,如何能快速定位到内存泄漏点并不容易。笔者通过使用 jemalloc(可以替换默认的 glibc 库)中的 profiling 机制(通过对程

[转帖]【技术剖析】9. 使用 NMT 和 pmap 解决 JVM 资源泄漏问题

https://bbs.huaweicloud.com/forum/thread-168749-1-1.html 作者:宋尧飞 > 编者按:笔者使用 JDK 自带的内存跟踪工具 NMT 和 Linux 自带的 pmap 解决了一个非常典型的资源泄漏问题。这个资源泄漏是由于 Java 程序员不正确地使