Daniel Fernández
Daniel Fernández

Reputation: 7465

How to make Byte Buddy load many types into the same wrapper class loader

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

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

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

Related Questions