Search code examples
javabytecode-manipulationbyte-buddy

Create a class constructor from scratch in ByteBuddy


I am trying to create a Java class from scratch using ByteBuddy. A class is supposed to have a bunch of private final properties and one constructor which initializes them with the arguments passed. I started with:

DynamicType.Builder<?> builder = new ByteBuddy()
                .subclass(Object.class)
                .implement(Serializable.class)
                .modifiers(Visibility.PUBLIC, TypeManifestation.FINAL)
                .name("Structure");

// for each property to be declared
builder = builder.defineField(bindingName, bindingType, visibility.PRIVATE, FieldManifestation.FINAL);
// end of for

builder = builder.defineConstructor(Visibility.PUBLIC)
                .withParameters(bindings)
                .intercept(/* Some implementation is supposed to go here*/);

I have several questions:

  1. Does ByteBuddy provide some suitable Implementation for that out-of-the-box?

  2. Is there somewhere an overview of ByteBuddy Implementation classes, provided out-of-the-box?

  3. If there is no such Implementation out-of-the-box, I'd be appreciated for some hints on how to make my own Implementation instance serving my purpose.


Solution

  • You can implement such a constructor by a combination of MethodCall and FieldAccessor:

    DynamicType.Builder<?> builder = ...;
    Implementation interceptor = StubMethod.INSTANCE;
    
    // for each field
    builder = builder.defineField(bindingName, 
                  bindingType, visibility.PRIVATE, FieldManifestation.FINAL);
    interceptor = FieldAccessor.ofField(bindingName)
                      .setsArgumentAt( ... )
                      .andThen(interceptor);
    
    interceptor = MethodCall.invoke( ... ).andThen(interceptor);
    

    The method call must invoke a specific constructor of either the instrumented class or the super class constructor (might be the default constructor of Object). The argument index needs to be the index of the argument that is assigned to the field (zero-based).