Byte-buddy:生成具有循环类型的类

Ste*_*uer 9 java byte-buddy

我正在尝试生成具有循环类依赖性的类,类似于这个问题:Byte Buddy - 处理生成的类中的循环引用

作为一个最小的例子,我想要生成的类有这样的依赖:

//class A depends on class B, and vice-versa
final class A { B theB; }
final class B { A theA; }
Run Code Online (Sandbox Code Playgroud)

上面链接中接受的答案没有为我提供足够的信息来实现这一点.这是我试过的:

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.jar.asm.Opcodes;

public class ByteBuddyHello {

    public static void main(String[] args) {
        try {
            final ByteBuddy bb = new ByteBuddy();
            final TypeDescription.Latent typeDescrA = new TypeDescription.Latent("A", 0, null, null);
            final TypeDescription.Latent typeDescrB = new TypeDescription.Latent("B", 0, null, null);
            final DynamicType.Unloaded<Object> madeA = bb
                    .subclass(Object.class)
                    .name("A")
                    .defineField("theB", typeDescrB, Opcodes.ACC_PUBLIC)
                    .make(); // exception thrown here!
            final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
                    .name("B")
                    .defineField("theA", typeDescrA, Opcodes.ACC_PUBLIC)
                    .make();

            Object a = madeA
                    .include(madeB)
                    .load(ByteBuddyHello.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
                    .getLoaded().newInstance();
            System.out.println(a.toString());
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我进入Exception in thread "main" java.lang.IllegalStateException: Cannot resolve declared type of a latent type description: class B标记线.

上面提到的问题的答案是"确保在正确定义潜在类型之前不加载类型",我猜这可能是我的问题.我不知道如何定义潜在类型虽然:-(

编辑:制作课程A以及B最终成绩(因为这将是理想的解决方案)

编辑:添加堆栈跟踪

Exception in thread "main" java.lang.IllegalStateException: Cannot resolve declared type of a latent type description: class B
    at net.bytebuddy.description.type.TypeDescription$Latent.getDeclaringType(TypeDescription.java:7613)
    at net.bytebuddy.description.type.TypeDescription$AbstractBase.getSegmentCount(TypeDescription.java:6833)
    at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onNonGenericType(AnnotationAppender.java:617)
    at net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations.onNonGenericType(AnnotationAppender.java:333)
    at net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType.accept(TypeDescription.java:3364)
    at net.bytebuddy.implementation.attribute.FieldAttributeAppender$ForInstrumentedField.apply(FieldAttributeAppender.java:122)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool$Record$ForExplicitField.apply(TypeWriter.java:270)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:4156)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1633)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:174)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:155)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2559)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2661)
    at my.package.playground.ByteBuddyHello.main(ByteBuddyHello.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Run Code Online (Sandbox Code Playgroud)

Raf*_*ter 3

这是Byte Buddy的一个bug;类型注释的解析器需要知道任何类型描述​​的深度,因此解析任何类型描述​​的类型路径。对于潜在类型,此深度始终为 0,但默认实现应用更复杂的解决方案。

这将在下一版本中修复。同时,对潜在类型描述进行子类化并重写该方法以返回 0。

我决定不更改TypeDescription.Latent类型,而是使InstrumentedType.Default实现更易于访问。使用后一种类型,它允许您定义任何用户都可见的循环类型的功能。这样,如果您想定义Implementation针对此功能进行验证的代码,您可以指定现有字段和方法。