ByteBuddy 在 Aspect 中初始化非原始字段

问题描述 投票:0回答:1

为了监控和程序分析,我目前正在尝试将 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
)?

instrumentation byte-buddy
1个回答
0
投票

您是否将这些字段添加到检测类中并从那里初始化它们?大多数监控工具都支持重新转换,其中不可能添加字段,并且任何值都附加到当前线程或弱引用存储中。

如果您想在每个类中添加这些字段,您需要按照您的建议进行编码。然而,没有必要将其添加到每个建议中。您可以:

  1. 创建多个建议类,并将“字段设置建议”链接到实际建议类之前。
  2. 提出你的建议。这通常发生在使用 Maven 等工具构建期间。 Byte Buddy 附带了一个构建工具。这样你就可以将重复的代码添加到每个建议的“输入”阶段。
© www.soinside.com 2019 - 2024. All rights reserved.