Search code examples
byte-buddy

Doing Cyclic Types in ByteBuddy


I am trying to dynamically create cyclic classes like this with byte-buddy:

class A{
 B b;
}
class B{
  A a;
}

I have looked at this example and I have written this code.

public static void main(String[] args) throws Exception {

    final ByteBuddy bb = new ByteBuddy();

    TypeDescription.Generic g1 = TypeDescription.Generic.Builder.rawType(Object.class).build();
    final InstrumentedType typeDescrB = InstrumentedType.Default.of("B", g1, Modifier.PUBLIC);

    final DynamicType.Unloaded<Object> madeA = bb
            .subclass(Object.class)
            .name("A")
            .defineField("theB", typeDescrB, Modifier.PUBLIC).make();

    final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
            .name("B")
            .defineField("theA", madeA.getTypeDescription()).make();

    Class a = madeA.include(madeB)
            .load(Test.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
            .getLoaded();

    for (Field f : a.getFields()) {
        System.out.println(f + "|" + f.getType().getName());
    }
    System.out.println("====");
    for (Field f : a.getField("theB").getType().getFields()) {
        System.out.println(f + "|" + f.getType().getName());
    }
}

After running the code I get this results

public B A.theB|B
====
Process finished with exit code 0

which means the Class B does not contain the field a. Does anybody know what is the problem?


Solution

  • I'm guessing that what you're seeing is just a mistake in your code.

    With this code:

    final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
        .name("B")
        .defineField("theA", madeA.getTypeDescription()).make();
    

    …you have made the field non-public (note that you specified PUBLIC for the other field, but not here). Then with this code:

    for (Field f : a.getField("theB").getType().getFields()) {
        System.out.println(f + "|" + f.getType().getName());
    }
    

    …you have asked for only public fields. Perhaps you meant getDeclaredFields()?