11

I am using ByteBuddy to create a class at runtime with dynamically generated byte code. The generated class does what it is intended to do, but I want to manually inspect the generated byte code, to ensure it is correct.

For example

Class<?> dynamicType = new ByteBuddy()
        .subclass(MyAbstractClass.class)
        .method(named("mymethod"))
        .intercept(new MyImplementation(args))
        .make()
        .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
        .getLoaded();

where MyImplementation chains multiple StackManipulation commands together to create the dynamically generated code.

Can I write the generated class out to a file, (so I can manually inspect with a IDE), or otherwise print out the bytecode for the generated class?

bramp
  • 9,581
  • 5
  • 40
  • 46

2 Answers2

15

You can save the class as .class file:

new ByteBuddy()
    .subclass(Object.class)
    .name("Foo")
    .make()
    .saveIn(new File("c:/temp"));

This code creates c:/temp/Foo.class.

5

Find below an example to store the bytes of the generated class in a byte array. And how the class can be saved to the file system and can be instantiated from this array.

import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.instrumentation.FixedValue;
import static net.bytebuddy.instrumentation.method.matcher.MethodMatchers.named;

public class GenerateClass extends ClassLoader {

    void doStuff() throws Exception {
        byte[] classBytes = new ByteBuddy()
                .subclass(Object.class)
                .name("MyClass")
                .method(named("toString"))
                .intercept(FixedValue.value("Hello World!"))
                .make()
                .getBytes();

        // store the MyClass.class file on the file system
        Files.write(Paths.get("MyClass.class"), classBytes, StandardOpenOption.CREATE);

        // create an instance of the class from the byte array
        Class<?> defineClass = defineClass("MyClass", classBytes, 0, classBytes.length);
        System.out.println(defineClass.newInstance());
    }

    public static void main(String[] args) throws Exception {
        new GenerateClass().doStuff();
    }
}
SubOptimal
  • 22,518
  • 3
  • 53
  • 69
  • Thanks SubOptimal. I accepted saka1029's answer, because it was shorter and achieved the same thing. – bramp Jun 16 '15 at 20:51
  • @bramp That's ok. Because the answers are solving different things. The answer from saka1029 generate the class and save it to a file. My answer generate the class, save it to a file and you can instantiate the generated class. If you don't need to instantiate the generated class or don't need access to the generated bytes, saka1029's answer is the way to go. – SubOptimal Jun 17 '15 at 06:09