博客
关于我
Java JFR 民间指南 - 事件详解 - jdk.ObjectAllocationSample
阅读量:477 次
发布时间:2019-03-06

本文共 3939 字,大约阅读时间需要 13 分钟。

Java 16 中的对象分配采样事件:JDK ObjectAllocationSample

引入

在 Java 16 中,JDK 引入了一个新的事件 ObjectAllocationSample,用于监控对象分配过程中的关键问题。这个事件的主要目的是帮助开发者识别在高负载环境下可能导致性能瓶颈的对象分配行为。


事件背景

在大多数 Java 应用中,对象的分配主要发生在 TLAB(Thread-Local Allocation Buffer)中。如果 TLAB 外分配或重分配过多,可能会导致内存管理问题。为了更好地监控这些问题,JDK 提供了两个事件:ObjectAllocationOutsideTLABObjectAllocationInNewTLAB。然而,这些事件默认会记录堆栈信息,这在高负载情况下会显著增加性能开销。为了解决这一问题,ObjectAllocationSample 事件被引入,通过采样机制来减少对堆栈信息的采集,从而平衡监控与性能之间的关系。


事件配置

Java 16 的默认配置

属性 描述
enabled true 默认启用。
throttle 150/s 每秒最多采集 150 个事件。
stackTrace true 采集事件时同时记录堆栈信息。

采样配置

属性 描述
enabled true 默认启用。
throttle 300/s 每秒最多采集 300 个事件。
stackTrace true 采集事件时同时记录堆栈信息。

事件包含的属性

属性 说明 示例
startTime 事件开始时间(格式化为 HH:mm:ss.fff)。 10:16:24.677
objectClass 触发事件的对象类。 byte[] (classLoader = bootstrap)
weight 该线程距离上次被采集 ObjectAllocationSample 事件的时间内,线程分配的对象总大小。 10.0 MB
eventThread 事件所属线程。 "main"(线程 ID 为 1)。
stackTrace 线程堆栈信息。 com.github.hashjang.jfr.test.TestObjectAllocationSample.main(String[]) line: 42

测试示例

以下是一个使用 ObjectAllocationSample 事件的测试案例。该测试模拟了多线程环境下的对象分配,展示了事件的采集情况:

public class TestObjectAllocationSample {    private static final int BYTE_ARRAY_OVERHEAD = 16;    private static final int OBJECT_SIZE = 1024 * 1024;    private static final int OBJECTS_TO_ALLOCATE = 20;    private static final String BYTE_ARRAY_CLASS_NAME = new byte[0].getClass().getName();    private static final String INT_ARRAY_CLASS_NAME = new int[0].getClass().getName();    private static final String EVENT_NAME = "jdk.ObjectAllocationSample";    public static byte[] tmp;    public static int[] tmp2;    public static void main(String[] args) throws IOException, InterruptedException {        WhiteBox whiteBox = WhiteBox.getWhiteBox();        whiteBox.fullGC();        Recording recording = new Recording();        recording.enable(EVENT_NAME).with("throttle", "1/s");        recording.start();        Runnable runnable = () -> {            for (int i = 0; i < OBJECTS_TO_ALLOCATE; ++i) {                tmp = new byte[OBJECT_SIZE - BYTE_ARRAY_OVERHEAD];                TimeUnit.MILLISECONDS.sleep(100);            }        };        Thread thread = new Thread(runnable);        Thread thread2 = new Thread(() -> {            for (int i = 0; i < OBJECTS_TO_ALLOCATE; ++i) {                tmp2 = new int[OBJECT_SIZE - BYTE_ARRAY_OVERHEAD];                TimeUnit.MILLISECONDS.sleep(100);            }        });        thread.start();        thread2.start();        thread.join();        thread2.join();        recording.stop();        Path path = new File(new File(".").getAbsolutePath(), "recording-" + recording.getId() + "-pid" + ProcessHandle.current().pid() + ".jfr").toPath();        recording.dump(path);        for (RecordedEvent event : RecordingFile.readAllEvents(path)) {            if (!EVENT_NAME.equals(event.getEventType().getName())) {                continue;            }            String objectClassName = event.getString("objectClass.name");            boolean isMyEvent = (Thread.currentThread().getId() == event.getThread().getJavaThreadId() ||                                 thread.getId() == event.getThread().getJavaThreadId() ||                                 thread2.getId() == event.getThread().getJavaThreadId()) &&                               (objectClassName.equals(BYTE_ARRAY_CLASS_NAME) || objectClassName.equals(INT_ARRAY_CLASS_NAME));            if (!isMyEvent) {                continue;            }            System.out.println(event);        }    }}

事件的底层原理

Java 对象分配流程

  • TLAB 分配:如果 TLAB 有足够空间,则在 TLAB 中分配对象。
  • TLAB 重分配:如果 TLAB 满不够空间,但浪费空间未超过阈值,则扩展 TLAB。
  • TLAB 外分配:如果以上条件不满足,则在堆外分配对象。
  • ObjectAllocationSample 事件的采样机制

  • Throttle 配置:通过 EWMA 算法实现动态控制采样频率,确保在高负载情况下不会过度采集。
  • 权重计算:记录线程距离上次采集的时间内分配的对象总大小,作为事件的 weight 属性。
  • 优化采样:对大对象分配采样次数增加,以提高采集准确性。

  • 总结

    • ObjectAllocationSample 是 Java 16 中用于优化对象分配监控的重要事件。
    • 事件的 objectClass 属性表示分配的对象类型,weight 属性表示线程分配的对象总大小。
    • JVM 通过动态调整采样频率(基于 EWMA 算法),保证在高负载环境下依然能够有效监控对象分配问题。
    • 建议在实际应用中根据性能需求调整采样频率,并结合堆栈信息分析,找到分配瓶颈并优化代码。

    转载地址:http://yjgbz.baihongyu.com/

    你可能感兴趣的文章
    Nginx 负载均衡与权重配置解析
    查看>>
    Nginx 负载均衡详解
    查看>>
    nginx 配置 单页面应用的解决方案
    查看>>
    nginx 配置https(一)—— 自签名证书
    查看>>
    nginx 配置~~~本身就是一个静态资源的服务器
    查看>>
    Nginx 配置清单(一篇够用)
    查看>>
    Nginx 配置解析:从基础到高级应用指南
    查看>>
    nginx+php的搭建
    查看>>
    nginx+tomcat+memcached
    查看>>
    nginx+Tomcat性能监控
    查看>>
    nginx+uwsgi+django
    查看>>
    Nginx-http-flv-module流媒体服务器搭建+模拟推流+flv.js在前端html和Vue中播放HTTP-FLV视频流
    查看>>
    Nginx下配置codeigniter框架方法
    查看>>
    Nginx之二:nginx.conf简单配置(参数详解)
    查看>>
    Nginx代理websocket配置(解决websocket异常断开连接tcp连接不断问题)
    查看>>
    Nginx代理初探
    查看>>
    Nginx代理外网映射
    查看>>
    Nginx代理模式下 log-format 获取客户端真实IP
    查看>>
    Nginx代理静态资源(gis瓦片图片)实现非固定ip的url适配网络环境映射ip下的资源请求解决方案
    查看>>
    Nginx反向代理与正向代理配置
    查看>>