如何在Java Mission Control事件浏览器中获取复合字段列
问题根因
你当前的代码写法不符合JFR(Java Flight Recorder)的序列化规则,这是复合字段无法显示的核心原因:
- JFR仅会自动序列化基础数据类型、String、枚举、标注了
@ContentType的内置值类型,以及配置了JFR注解的普通嵌套类;继承自jdk.jfr.Event的类本身是独立事件类型,不会作为另一个事件的嵌套字段被自动序列化内部属性。你现在Book类中声明的Author auther字段,实际只会被记录一个对象引用标识,不会存储name、age这类具体属性值,自然无法在JMC中展示。 - 顺带提两个代码里的拼写错误:字段名
auther应为author,测试代码里的Begginer应为Beginner,不会影响当前功能但容易引发后续维护问题。
可行解决方案
方案1:将Author定义为JFR复合类型(推荐,适合嵌套展示场景)
如果你需要把Author作为Book事件的内嵌属性直接展示,不要让Author继承Event类,给Author类加上JFR的类型注解即可被识别为可序列化的复合类型,修正后的代码如下:
package com.foo.bar; import jdk.jfr.*; public class AB { // 复合类型不需要继承Event @Name("com.foo.bar.Author") @Label("Author Info") public static class Author { @Label("Author Name") String authorName; @Label("Age") int age; @Label("Residence") String place; Author(String name, int age, String place) { this.authorName = name; this.age = age; this.place = place; } } @Name("com.foo.bar.Book") @Label("Book Event") public static class Book extends Event { @Label("Book Name") String name; @Label("Price") int price; @Label("Author Details") Author author; Book(String n, int p, Author author) { this.name = n; this.price = p; this.author = author; } } public static void main(String[] args) { Author author = new Author("John", 42, "USA"); Book b = new Book("Java for Beginner", 800, author); b.commit(); } }
用修正后的代码录制JFR日志后:
- 单条Book事件的详情面板会自动展开显示Author的所有内部字段
- 如果需要在事件浏览器表格列中直接展示Author的属性,点击表格右上角的列配置按钮,在嵌套的
author分类下勾选需要的字段(比如authorName、age),即可添加为独立列展示。
方案2:保留Author为独立事件,通过关联ID匹配
如果你需要Author本身作为独立事件被统计、查询(比如单独统计作者维度的事件),不要把Author实例作为Book的字段,改为给两个事件添加相同的关联标识字段:
- 给Author和Book事件都增加一个
long bizId或者String traceId字段,同一次业务操作产生的两个事件写入相同的ID值 - 录制完成后,在JMC事件浏览器中可以通过相同ID分别匹配对应的Book和Author事件,拿到关联的作者详情,这种方式适合两个事件生命周期不绑定的场景。
JMC对复合类型列展示的支持说明
JMC事件浏览器原生支持复合类型字段的展示,只是默认不会自动把所有嵌套字段展开为表格列,需要手动在列设置中勾选需要的嵌套属性。如果是未被JFR正确序列化的引用类型(比如你最初直接把Event子类作为字段引用的写法),JFR录制文件里本身就没有存储对应字段的实际内容,无论怎么配置列都无法展示详情。
内容的提问来源于stack exchange,提问作者Niwedita Rani
相关产品推荐
相关产品推荐

