【问题标题】:bytebuddy - add class level annotationbytebuddy - 添加类级别注释
【发布时间】:2021-07-02 05:27:45
【问题描述】:

我正在尝试使用 byte-buddy 创建 java 代理,以允许在运行时修改某些类 -

FirstSeleniumTest 类已经存在 - 我想添加如下注释:

@org.testng.annotations.Listeners(value = org.deployd.test.TestNgListener.class)
public class FirstSeleniumTest {...

这是我在代理中的 premain 方法:

new AgentBuilder.Default()
            .disableClassFormatChanges()
            .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
            .with(AgentBuilder.TypeStrategy.Default.REDEFINE)
            .type(ElementMatchers.nameContains("org.deployd"))
            .transform((builder, typeDescription, agr3, arg4) -> builder
                    .annotateType(AnnotationDescription.Builder.ofType(Listeners.class)
                            .define("value", TestNgListener.class)
                            .build()))
            .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
            .installOn(instrumentation);

在执行过程中出现以下错误:

[Byte Buddy] DISCOVERY org.deployd.test.FirstSeleniumTest 
[sun.misc.Launcher$AppClassLoader@18b4aac2, null, loaded=false]
[Byte Buddy] ERROR org.deployd.test.FirstSeleniumTest 
[sun.misc.Launcher$AppClassLoader@18b4aac2, null, loaded=false]
java.lang.IllegalArgumentException: class org.deployd.agent.TestNgListener cannot be 
assigned to value
at net.bytebuddy.description.annotation.AnnotationDescription$Builder.define(AnnotationDescription.java:860)
at net.bytebuddy.description.annotation.AnnotationDescription$Builder.define(AnnotationDescription.java:947)
at net.bytebuddy.description.annotation.AnnotationDescription$Builder.define(AnnotationDescription.java:935)
at org.deployd.agent.TestAgent.lambda$premain$0(TestAgent.java:41)

如果我手动添加注释:

@org.testng.annotations.Listeners(value = org.deployd.test.TestNgListener.class)
public class FirstSeleniumTest {...

那么没有错误 - 意味着值'value'对于给定的注释是正确的。

关于我在尝试为已经退出的类创建带有字节伙伴的类级别注释时可能会丢失的任何指针。谢谢。

【问题讨论】:

    标签: byte-buddy javaagents


    【解决方案1】:

    如果你想定义一个数组属性,你必须这样声明它:

    AnnotationDescription.Builder.ofType(Listeners.class)
      .define("value", new Class<?>[] { TestNgListener.class })
      .build();
    

    会起作用。 Byte Buddy 不像 Java 编程语言那样将此类数组视为可变参数。

    【讨论】:

    • 谢谢@Rafael。我的理解是定义中的第二个参数期望“值”与真实实例的类类型?我认为这会引发编译错误?稍后会检查一下。
    • 是的,应该是这个 - defineTypeArray("value", TestNgListener.class)
    【解决方案2】:

    经过进一步分析,我发现注释 value 将数组与类型的单个值除外。我能够通过 javassist 解决这个问题,如下所示:

    AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
                Annotation annotation = new Annotation(Listeners.class.getName(), constPool);
                MemberValue[] memberValues = new MemberValue[]{new ClassMemberValue(TestNgListener.class.getName(), constPool)};
                ArrayMemberValue arrayMemberValue = new ArrayMemberValue(constPool);
                arrayMemberValue.setValue(memberValues);
                annotation.addMemberValue("value", arrayMemberValue);
                annotationsAttribute.addAnnotation(annotation);
                ctClass.getClassFile().addAttribute(annotationsAttribute);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-23
      • 1970-01-01
      • 2012-01-14
      • 2016-10-24
      • 2017-10-23
      相关资源
      最近更新 更多