为了监控和程序分析,我目前正在尝试将 AspectJ 实现转换为一个 ByteBuddy 和一个 javassist 实现。原始的 AspectJ 实现在这里:https://github.com/kieker-monitoring/kieker/blob/c95292abc8df91eac82c1fa9f6ab0316768df16b/monitoring/src/kieker/monitoring/probe/aspectj/operationExecution/AbstractOperationExecutionAspect.java#L43
不幸的是,我没有看到在 ByteBuddy 中初始化非原始字段的方法。在 AspectJ 中,我可以将它们放在建议中,在 javassist 中,我可以使用 API 添加它们(https://github.com/kieker-monitoring/kieker/blob/KIEKER-1973-InstrumentationTechnologies/monitoring-probe -javassist/src/kieker/monitoring/probe/javassist/KiekerClassTransformer.java#L107),然后在代表程序代码的字符串中使用它们(例如 CFREGISTRY:https://github.com/kieker-监控/kieker/blob/547adbf71b4347ec95abec16bfd54a5845b48f58/monitoring-probe-javassist/src/kieker/monitoring/probe/javassist/KiekerClassTransformer.java#L74).
但是对于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;
}
(https://github.com/kieker-monitoring/kieker/blob/d1eff598ce4d1bbf226cc76c51aa3ac8f8db2b7e/monitoring-probe-bytebuddy/src/kieker/monitoring/probe/bytebuddy/OperationExecutionAdvice.java#L14)但很可能会创建一些开销并使 JVM 优化变得不可能,因为字段设置为
readOnly=false
。
因此创建字段还需要以某种方式设置初始值设定项:
.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;
}
})
(在 https://github.com/kieker-monitoring/kieker/blob/d1eff598ce4d1bbf226cc76c51aa3ac8f8db2b7e/monitoring-probe-bytebuddy/src/kieker/monitoring/probe/bytebuddy/PremainClass.java#L93)。不幸的是,我没有看到这样做的选择;我只能调用
.value(..)
来设置原始类型,但无法设置初始值设定项。
bytebuddy定义字段并初始化一个复杂对象似乎尝试过类似的事情,但是根据this,没有办法这样做。
另一个选择是添加一个静态初始化块,这使得可以将字段设置为
readOnly=true
(但 final
也不起作用),就像在 ByteBuddy:生成静态初始化器? .
总的来说:有没有办法初始化 ByteBuddy 动态创建的
static final
字段(或者至少可以设置它们 readOnly
)?
您是否将这些字段添加到检测类中并从那里初始化它们?大多数监控工具都支持重新转换,其中不可能添加字段,并且任何值都附加到当前线程或弱引用存储中。
如果您想在每个类中添加这些字段,您需要按照您的建议进行编码。然而,没有必要将其添加到每个建议中。您可以: