深度探索JFR - JFR详细介绍与生产问题定位落地 - 3. 各种Event详细说明与JVM调优策略(1)

Event 采集详细配置

目前,JDK 11 一共有136个 Event 采集配置。这里会比较详细的去看每一个Event,并说明基本应用,建议配置。如果 default.jfc 中没有打开或者需要修改的配置,会将配置文件代码发出来。

1. JFR 相关 Event

一共4个 Event,但是需要关心的就下面这两个

  • Data Loss:数局丢失 Event,当有数据发生丢失时,会有这个Event 进行记录。包括开始时间,Amount(本次丢失多少事件),Total(一共丢失多少事件)
  • Recording Setting:记录详细配置采集 Event,会在每次产生新的 Data Chunk 的时候采集一次所有的 Event 的详细配置并记录到这个 Event 中。

这些在 default.jfc 中默认打开

2. JAVA 应用相关

2.1. TLAB 相关

众所周知,TLAB (Thread Local Allocation Buffer)目的是为类进行内存快速分配。堆内存所有线程共享访问,所以在堆内存上面分配对象,就会锁定整个堆,这样效率太低。TLAB 是位于堆内存上面的一块内存区域,在为每个线程分配 TLAB 的时候才会锁定堆(G1 是CAS分配)。分配对象的时候,优先从线程的 TLAB 上分配,这样就不用和其他线程同步。当对象比较大的时候,例如对于 G1 来说, HeapRegionSize 配置大小的一半以上的对象就被认为是大对象,大对象的分配不会发生在 TLAB,不在 TLAB 发生的对象分配会涉及到线程同步。

这是比较笼统的看法,针对于 G1,这个算法更加复杂。为了能说明 JFR 相关事件的意义,这里继续深入一下关于 G1 TLAB 相关原理。

创建一个对象时:

  1. 首先尝试从线程现有的TLAB空间分配内存
  2. 如果剩余空间不足,查看是否能分配一个新的TLAB,再分配内存给对象
  3. TLAB 的实现内部,每个线程维护一个 refill_waste 的变量,根据这个变量的值决定是否能分配一个新的TLAB。这个变量会根据一定算法随着线程的运行不断变化
  4. 同时, 每个线程的 TLAB 大小也是随着线程运行不断变化的
  5. 当 TLAB 剩余空间不足时,查看当前 TLAB 的剩余大小,如果小于 refill_waste 当前值,则认为 TLAB 该扩容了,需要分配一个新的TLAB,这时候,JFR 会产生一条 ObjectAllocationInNewTLAB Event 记录;如果不小于,则认为这个 TLAB 还不算满,当前这个对象直接走堆上内存分配,不从 TLAB 分配,这时会产生一条 ObjectAllocationOutsideTLAB Event 记录。

涉及的 Event 以及默认配置:

  • ObjectAllocationInNewTLAB: TLAB 扩容时产生的 Event
    • 在 default.jfc 中默认没有打开,可以通过向导配置 memory-profiling 调为 memory-profiling-enabled-medium 打开
    • 也可以用高级配置配置这个 Event 是否采集,以及堆栈是否采集
      -采集内容包括:时间,线程,本次需要分配内存大小,对象类型,当前 TLAB 大小
  • ObjectAllocationOutsideTLAB:
    • 在 default.jfc 中默认没有打开,可以通过向导配置 memory-profiling 调为 memory-profiling-enabled-medium 打开
    • 也可以用高级配置配置这个 Event 是否采集,以及堆栈是否采集
    • 采集内容包括:时间,线程,本次需要分配内存大小,对象类型

这两个的采集,对性能影响比较大,不能长期跑。尤其是在启用堆栈收集后,影响就更大了。一般考虑动态打开。

一般应用:

  1. 对于上一节里面需要确定 HeapRegionSize 大小的时候,可以考虑采集一段时间内的 ObjectAllocationOutsideTLAB Event,查看最大需要的内存大小是多少。
  2. 如果考虑通过减少内存分配,来减少 GC,或者定位大内存分配代码位置,可以打开这两个 Event 的采集,查看造成这些事件的热点堆栈是哪里,以此优化代码。

配置打开示例:

    <event name="jdk.ObjectAllocationInNewTLAB">
      <setting name="enabled">true</setting>
      <setting name="stackTrace">true</setting>
    </event>

    <event name="jdk.ObjectAllocationOutsideTLAB">
      <setting name="enabled">true</setting>
      <setting name="stackTrace">true</setting>
    </event>

事件 jmc 查看示例:

image

image

2.2. 文件操作相关

主要涉及三个 Event:

  • FileForce:强制写的时候,会产生这个 Event
  • FileRead:文件读的时候,会产生这个 Event
  • FileWrite:文件写的时候,会产生这个 Event

FileChannel举例:

try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "rw");
    FileChannel channel = reader.getChannel();
    ByteArrayOutputStream out = new ByteArrayOutputStream()) {
    int bufferSize = 1024;
    ByteBuffer buff = ByteBuffer.allocate(bufferSize);
    channel.read(buff); //产生 FileRead
    channel.write(buff); // 产生 FileWrite
    
    channel.force(true); // 强制不写入高速缓存,直接写入磁盘文件
    channel.write(buff); // 产生 FileForce
}

这三个事件配置可以采集堆栈,设置采集时间阈值。在 default.jfc 中,这三个事件默认都是采集的,堆栈采集打开,并且阈值是20ms。如果你的应用只是打日志用到了文件,那个这个默认配置就很足够了。尤其是对于 Log4j2 的异步日志,这个阈值是够用的。如果你的应用需要高频操作文件,例如 RocketMQ 的 日志文件(基于 mmap)的,则这个阈值最好改成10ms,因为对文件写入读取速度要求更高。

2.3. 异常与错误相关

主要涉及两个 Event:

  • Java Error Event:当有 Error 被 throw 时,会产生这个event, default.jfc 中默认开启这个采集,并且包括堆栈(配置项是 JavaErrorThrow)
  • Java Exception Event:当有 Exception 被 throw 时,会产生这个event,default.jfc 中默认不开启这个采集,并且包括堆栈(配置项是 JavaExceptionThrow)

我建议不用开启这两个 EVent 的采集,因为 Exception 我们可以通过日志分析, Error 一般框架都会有一些,一般与为我们的业务无关。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误提示是说在当前的环境中找不到名为jdk.jfr的程序包。可能是因为你的Java安装不完整或者没有正确配置环境变量。你需要检查一下Java的安装和环境变量设置,确保jdk.jfr这个包已经正确安装并且在环境变量中可以被找到。 ### 回答2: Java 是一种高级编程语言,它广泛用于各种应用程序的开发。使用 Java 编写的应用程序需要在运行时使用 Java 开发工具包(JDK)中的 Java 运行时环境(JRE)来运行。 当您尝试编写使用 Java Flight Recorder(JFR)的 Java 应用程序并运行时,可能会遇到错误“ 程序包jdk.jfr不存在 ”。这是因为 JDK 8 中的 Java Flight Recorder (JFR) 仅适用于 Oracle JDK 和 OpenJDK,而不适用于其他 Java 开发工具包。 如果您安装了其他 Java 开发工具包或版本,则可能无法访问 JFR 包。要解决此问题,您需要安装其他 JDK 或更新您的 JDK 版本以包含 JFR 包。 一种方法是在官方下载页面上下载 Oracle JDK 或 OpenJDK 的最新版本。在安装此版本后,您应该能够使用 JFR 包。 另一种方法是通过 Maven 或其他构建工具添加 JFR 包的依赖项。在 Maven 中,可以添加以下依赖项: ``` <dependency> <groupId>com.oracle.jdk</groupId> <artifactId>jfr</artifactId> <version>1.0.1</version> </dependency> ``` 请注意,这种方法需要您将 Maven 或其他构建工具配置为使用正确的 JDK。 总之,要解决“程序包 jdk.jfr 不存在”的问题,您需要确保您的 JDK 包含 JFR 或安装新的 JDK 版本。您还可以在构建工具中添加 JFR 依赖项以访问该包。 ### 回答3: 这个问题通常出现在你想要在Java代码中使用Java Flight Recorder (JFR)功能时。JDK JFR是Java Development Kit (JDK)中自带的一种用于线上Java应用程序的性能监控和故障分析工具。当你在使用JDK JFR时,可能会遇到“程序包jdk.jfr不存在”的问题。 这个错误通常是因为你的Java版本不支持JFR功能。检查一下你的JDK版本是否为JDK 7u40或以上版本,因为只有这些版本才支持JFR功能。如果你的版本较低,你需要升级以支持JFR功能。 如果你的JDK版本已经符合要求,则可能是JFR功能未正确安装。确认一下你的JDK目录中是否包含jfr.jar文件。如果没有,你可以从Oracle官网下载Oracle JDK二进制文件并重新安装JFR。 此外,如果你是在IDE中使用Java Flight Recorder,可以检查一下你的IDE配置是否正确,确保你已经将JFR文件路径添加到了CLASSPATH环境变量中。 最后,如果你已经尝试了以上方法,但仍然无法解决问题,你可以尝试使用替代方案,例如Java VisualVM、JProfiler、YourKit等工具,这些工具同样具有性能监控和故障分析功能,并且易于使用。 总之,当你遇到“程序包jdk.jfr不存在”的问题时,你应该检查你的JDK版本、JFR功能是否正确安装、IDE配置是否正确等可能原因,并尝试以替代方案来解决问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值