Reputation: 7465
I'm using Byte Buddy in a scenario in which I could potentially need to create several dozen thousand classes with it. These are independent classes implementing interfaces, not proxies.
Right now I'm loading my DynamicType.Unloaded<?>
instances into class loaders by wrapping one of my application's class loaders:
final Class<?> myClass =
unloadedType
.load(someAppClassLoader, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
This wrapping strategy is right for me, but I have the issue that every time I execute the code above a new, sealed ClassLoader
is created containing only the new class. I know I can "include" auxiliary types... but these are not auxiliary types, but fully independent classes.
As I have to create many thousands, I'm left with a huge amount of class loaders I don't really need, because I want to isolate bytebuddy-created classes from the rest, but not one from the other, nor have any need to have a new class loader created for each one. And my profiling shows quite a huge memory overhead from the large amount of class loaders (which in this case are quite heavy).
From my tests it seems I could use a wrapping strategy for the first one:
final Class<?> myClass =
type
.load(someAppClassLoader, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
...then retrieve the new class loader:
final ClassLoader bbClassLoader = myClass.getClassLoader();
...and then use this class loader in subsequent creations, by switching strategy to injection:
final Class<?> myOtherClass =
otherUnloadedType
.load(bbClassLoader, ClassLoadingStrategy.Default.INJECTION)
.getLoaded();
But this does not look like a clean strategy to me given it seems to be injecting via introspection in order to circumvent the fact that the class loader is sealed. So I wonder whether there is a better mechanism for doing this in Byte Buddy.
Note that in order to have a properly sealed class loader I could turn all my many thousands of DynamicType.Unloaded
objects into Class<?>
ones at once into a single class loader instance (and seal it). I can initialise all my classes at application bootstrap in a batch and then leave the class loader alone without further dynamic class creation.
What would be the proper strategy for a scenario like mine?
Upvotes: 2
Views: 1217
Reputation: 44032
The class loader that is created when using a WRAPPER
strategy allows for loading classes later in the class loader's life-cycle. For security reasons, this needs to be enabled by calling opened()
on the strategy.
You can then cast the first class loader to InjectionClassLoader
which allows for using InjectionClassLoader.Strategy.INSTANCE
where additional classes can be injected without any unsafe API.
You can also combine multiple DynamicType
instance by calling include
and then load all classes using WRAPPER
in one wash.
Upvotes: 2