序言
愿君多采撷,此物最相思。
整理JFR相关知识 。
什么是JFR?
JFR 是 Java Flight Record (Java飞行记录) 的缩写,是 JVM 内置的基于事件的JDK监控记录框架。这个起名就是参考了黑匣子对于飞机的作用,将Java进程比喻成飞机飞行,==主要用于问题定位和持续监控==。
JFR性能非常高效,对于业务影响很小,因为这个框架本来就是用来长期在线上部署的框架。这个记录可以输出成二进制文件,用户可以指定最大记录时间,或者最大记录大小,供用户在需要的时候输出成文件进行事后分析。
JFR 的前身也是 JFR,只不过这个 J 不是 Java 而是 JRockit。在 JRockit 虚拟机时代,就有这样一个工具用来记录 Java 虚拟机运行时各项数据。在 Oracle 收购 Sun 公司之后,Hotspot 虚拟机时代,也一直延续了这个工具:
- JFR 0.9 版本对应 JDK 7 和JDK 8:
- 在 JDK 8u40 之后,可以在运行时灵活地打开关闭 JFR。
- JFR 1.0 版本对应 JDK 9 和 JDK 10: 在这一版本之后,增加了 JFR 事件接口,用户可以生产或者消费某种事件。
- JFR 2.0 版本对应 JDK 11,详细讨论说明。
JFR具有以下关键的特性:
低开销,可在生产环境核心业务进程中始终在线运行。
可以进行运行时分析,可以分析 Java 应用程序,JVM 内部以及当前Java进程运行环境等多因素。
JFR基于事件采集,可以分析非常底层的信息,例如对象分配,方法采样与热点方法定位与调用堆栈,安全点分析与锁占用时长与堆栈分析,GC 相关分析以及 JIT 编译器相关分析(例如 CodeCache )
完善的 API 定义,用户可以自定义事件的生产与消费。
核心-Event事件
在 JFR中,一切皆为 Event:
- 任意JVM行为都是一个Event,类加载对应 Class Load Event
- 开启 JFR 记录也是一个Event,对应的就是 Recording Reason Event
- 就算是有 Event 丢失,他也是一个 Event,对应 Data Loss Event
Event 在特定的时间点产生,每个Event是由名称,时间戳还有 Event Payload组成。
Event Payload包含例如 CPU负载、Event 发生之前还有之后的 Java 堆大小、 获取锁的线程 ID 等等。
大部分的 Event,都有 Event 是在哪个线程发生的,Event 发生的时候这个线程的调用栈,Event 的持续时间。
利用这些信息,我们可以回溯 Event 发生当时的情况。
Event 分类
Event 按照采集方式可以分为三种:
- Instant Event:顾名思义,这种 Event 在发生时就立刻采集。例如:Throw Exception Event 还有 Thread Start Event,类似于这种==在某一时刻发生的 Event==。
- Duration Event:这种 Event 需要耗费一些时间,在完成的时候会记录。对于这种类型的 Event,可以设置一个时间限制,超过这个时间限制的才会记录。例如 GC Event,Thread Sleep Event。
- Sample Event(Requestable Event):按照一定的频率采集,这个频率是可以配置的。例如 Thread Dump Event,Method Sampling Event
由于 JFR 会采集很多很多的数据,为了效率,最好配置自己感兴趣的事件采集;
对于 Duration Event 设置时间限制,一般我们对于时间短的事件并不关心。
Event 会被写入 .jfr 的二进制文件(二进制文件对于应用来说读写效率最高)中,以 little endian base 128 的形式编码,这里我们用一个 Event 举个例子: