如何用ByteBuddy初始化切面中的非基本类型static final字段?
ByteBuddy初始化静态final非基本类型字段的问题
我正在为Kieker监控实现程序分析功能,需要将原有AspectJ探针转换为ByteBuddy和Javassist版本。在AspectJ中可以直接在通知里声明字段,Javassist也能通过API添加字段并在代码中引用,但ByteBuddy里初始化非基本类型字段遇到了障碍。
当前实现的性能问题
目前我通过在每次方法进入通知中检查并初始化字段的方式实现功能,代码如下:
@Advice.OnMethodEnter public static OperationStartData enter( @Advice.Origin String operationSignature, @Advice.FieldValue(value = "CTRLINST", readOnly = false) IMonitoringController CTRLINST, @Advice.FieldValue(value = "TIME", readOnly = false) ITimeSource TIME, @Advice.FieldValue(value = "VMNAME", readOnly = false) String VMNAME, @Advice.FieldValue(value = "CFREGISTRY", readOnly = false) ControlFlowRegistry CFREGISTRY, @Advice.FieldValue(value = "SESSIONREGISTRY", readOnly = false) SessionRegistry SESSIONREGISTRY) { if (CTRLINST == null) { CTRLINST = MonitoringController.getInstance(); TIME = CTRLINST.getTimeSource(); VMNAME = CTRLINST.getHostname(); CFREGISTRY = ControlFlowRegistry.INSTANCE; SESSIONREGISTRY = SessionRegistry.INSTANCE; } // 后续业务逻辑 }
该方案存在明显缺陷:
- 每次方法执行都要进行null检查,带来额外性能开销
- 字段必须设置为
readOnly=false,JVM无法对相关代码做优化
尝试defineField的局限
我尝试用ByteBuddy的defineField创建静态final字段,代码如下:
.transform(new AgentBuilder.Transformer() { @Override public Builder<?> transform(Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) { Valuable<?> definedField = builder.defineField("CTRLINST", IMonitoringController.class, Modifier.STATIC | Modifier.FINAL | Modifier.PRIVATE); return definedField; } })
但defineField仅支持通过.value(..)设置基本类型的初始值,无法为非基本类型字段添加自定义初始化逻辑(比如调用单例工厂方法获取实例)。
待验证的静态初始化块方案
我考虑过通过添加静态初始化块来完成字段初始化,这样字段可以设置为readOnly=true,但不确定是否能将字段标记为final,也不确定这种方案的可行性。
核心疑问
- 是否存在方法可以初始化ByteBuddy动态创建的
static final非基本类型字段? - 如果无法实现
static final,有没有办法将字段设置为readOnly以获得JVM优化的性能收益?
内容的提问来源于stack exchange,提问作者David Georg Reichelt
相关产品推荐
相关产品推荐

