如何让 Byte Buddy 将多种类型加载到同一个包装器 class 加载器中

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

我在一个场景中使用 Byte Buddy,我可能需要用它创建几十万个 classes。这些是独立的 classes 实现接口,而不是代理。

现在我正在通过包装我的应用程序的 class 加载程序之一将我的 DynamicType.Unloaded<?> 实例加载到 class 加载程序中:

final Class<?> myClass =
    unloadedType
        .load(someAppClassLoader, ClassLoadingStrategy.Default.WRAPPER)
        .getLoaded();

这种包装策略适合我,但我有一个问题,每次我执行上面的代码时,都会创建一个新的、密封的 ClassLoader,其中只包含新的 class。我知道我可以 "include" 辅助类型...但这些不是辅助类型,而是完全独立的 classes.

由于我必须创建数千个,所以我剩下大量 class 我并不真正需要的加载器,因为我想将 bytebuddy 创建的 classes 从其余的,但不是彼此之间的一个,也不需要为每个创建一个新的 class 加载程序。我的分析显示大量 class 加载器(在本例中非常重)会产生相当大的内存开销。

从我的测试来看,我似乎可以对第一个使用包装策略:

final Class<?> myClass =
    type
        .load(someAppClassLoader, ClassLoadingStrategy.Default.WRAPPER)
        .getLoaded();

...然后检索新的 class 加载程序:

final ClassLoader bbClassLoader = myClass.getClassLoader();

...然后在后续创建中使用此 class 加载程序,方法是将策略切换为 injection:

final Class<?> myOtherClass =
    otherUnloadedType
        .load(bbClassLoader, ClassLoadingStrategy.Default.INJECTION)
        .getLoaded();

但这对我来说看起来不像是 clean 策略,因为它似乎是通过内省注入以规避 class 加载器被密封的事实.所以我想知道在字节好友中是否有更好的机制来做到这一点。

请注意,为了有一个正确的 密封 class 加载程序,我可以将我所有成千上万的 DynamicType.Unloaded 对象变成 Class<?>一次进入单个 class 加载程序实例(并密封它)。我可以在应用程序 bootstrap 中批量初始化我所有的 classes,然后单独留下 class 加载器,无需进一步动态 class 创建。

对于像我这样的情况,正确的策略是什么?

使用 WRAPPER 策略时创建的 class 加载程序允许在 class 加载程序的生命周期后期加载 classes。出于安全原因,这需要通过调用策略 opened() 来启用。

然后您可以将第一个 class 加载程序转换为 InjectionClassLoader,这允许使用 InjectionClassLoader.Strategy.INSTANCE,其中可以注入额外的 classes 而没有任何不安全 API.

您还可以通过调用 include 组合多个 DynamicType 实例,然后使用 WRAPPER 一次性加载所有 classes。