Let's say I want to dynamically create class B <: A that I require to be visible everywhere where A is visible.
(Strictly speaking, I want to create class B <: A as an alternative to existing C <: A and require it to be visible everywhere, where C is visible. But that's a detail.)
And if I understood the classloader hierarchy thing correctly, getting B loaded from the same classloader that loaded A should do the trick.
ByteBuddy has this feature of specifying at which classloader to inject a new class
ByteBuddy byteBuddy = new ByteBuddy();
DynamicType.Builder builder = byteBuddy
.subclass(A.class)
.name("B")
.andSoOn
.blah
;
DynamicType.Unloaded<?> loadable = builder.make();
loadable.load(A.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION);
I can get the produced bytecode by means of
byte[] bytecode = loadable.getBytes();
Which I can then modify and reload.
I've run into some issues with that, though: Why doesn't ASM call my ``visitCode``?
and even if I could get that to work, I don't know if that loading process would re-execute the static initialiser (which I want it to and what I was trying to test with the code in the other question) or not.
So the "safer" route would be to get finished bytecode from ASM before loading the class and then directly load that bytecode.
How do I do that, though?
The "obvious" approach would be to get a DynamicType.Unloaded from the byte[] and then use its load method like above.
I cannot seem to find a way to do that, though.
ClassLoaderByteArrayInjector has a very promising name. But it expects a TypeDescriptor, which -- again -- I cannot seem to get for an unloaded class.
How do I pull this off?