Byte-buddy: generate classes with cyclic types

前端 未结 2 475
日久生厌
日久生厌 2021-01-17 21:16

I\'m trying to generate classes with a cyclic class dependency, similar to this question: Byte Buddy - Handling cyclic references in generated classes

As a minimal e

相关标签:
2条回答
  • 2021-01-17 21:38

    This is a working solution, following the accepted answer:

    import net.bytebuddy.ByteBuddy;
    import net.bytebuddy.description.annotation.AnnotationList;
    import net.bytebuddy.description.modifier.ModifierContributor;
    import net.bytebuddy.description.modifier.TypeManifestation;
    import net.bytebuddy.description.modifier.Visibility;
    import net.bytebuddy.description.type.TypeDescription;
    import net.bytebuddy.dynamic.DynamicType;
    import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
    import net.bytebuddy.jar.asm.Opcodes;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    
    class TypeDescrFix extends TypeDescription.Latent {
        TypeDescrFix(final String name, final int modifiers, final Generic superClass, final List<? extends Generic> interfaces) {
            super(name, modifiers, superClass, interfaces);
        }
    
        @Override
        public int getSegmentCount() {
            return 0;
        }
    
        @Override
        public AnnotationList getDeclaredAnnotations() {
            return new AnnotationList.Empty();
        }
    }
    
    public class ByteBuddyHello {
    
        public static void main(String[] args) {
            try {
                final ByteBuddy bb = new ByteBuddy();
                final TypeDescription.Latent typeDescrA = new TypeDescrFix("A", 0, null, null);
                final TypeDescription.Latent typeDescrB = new TypeDescrFix("B", 0, null, null);
                final DynamicType.Unloaded<Object> madeA = bb
                        .subclass(Object.class)
                        .name("A")
                        .modifiers(ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.FINAL).resolve())
                        .defineField("theB", typeDescrB, Opcodes.ACC_PUBLIC)
                        .make();
                final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
                        .name("B")
                        .modifiers(ModifierContributor.Resolver.of(Visibility.PUBLIC, TypeManifestation.FINAL).resolve())
                        .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());
    
                final File folder = new File("/tmp/ByteBuddyHello");
                madeA.saveIn(folder);
                madeB.saveIn(folder);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-17 22:02

    This is a bug in Byte Buddy; the resolver for type annotations needs to know the depth of any type description and therefore resolves the type path of any type description. For latent types, this depth is always 0 but the default implementation applies a more complex solution.

    This will be fixed in the next release. In the meantime, subclass the latent type description and override the method to return 0.

    I decided not to change the TypeDescription.Latent type but rather make the InstrumentedType.Default implementation more accessible. Use the latter type which allows you to define features of the cyclic type which will be visible to any user. This way, you can for example specify existing fields and methods if you want to define Implementations that validate against this feature.

    0 讨论(0)
提交回复
热议问题