如何使Byte Buddy将许多类型的内容加载到同一包装类加载器中

时间:2019-04-05 13:21:42

标签: java classloader introspection byte-buddy bytecode-manipulation

在可能需要用它创建几十万个类的情况下,我正在使用Byte Buddy。这些是实现接口的独立类,而不是代理。

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

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

此包装策略适合我,但是我遇到的问题是,每次执行代码时,都会创建一个仅包含新类的新的密封ClassLoader上方的代码。我知道我可以“包括”辅助类型...但是这些不是辅助类型,而是完全独立的类。

由于我必须创建成千上万的类,所以我剩下了许多我真正不需要的类加载器,因为我想将bytebuddy创建的类与其他类隔离开来,而不是彼此隔离,也不要不需要为每个类创建一个新的类加载器。而且我的分析显示,大量的类加载器(在这种情况下非常重)会占用大量内存。

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

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

...然后检索新的类加载器:

final ClassLoader bbClassLoader = myClass.getClassLoader();

...,然后通过将策略切换为注入

,在随后的创建中使用此类加载器:
final Class<?> myOtherClass =
    otherUnloadedType
        .load(bbClassLoader, ClassLoadingStrategy.Default.INJECTION)
        .getLoaded();

但是,对于我来说,这似乎不是一种 clean 策略,因为它似乎是通过自省进行注入的,目的是规避类加载器是密封的这一事实。因此,我想知道在Byte Buddy中是否存在更好的机制。

请注意,为了拥有正确的密封类加载器,我可以将所有成千上万的{{​​1}}对象一次转换为DynamicType.Unloaded个对象,成为一个类加载器实例(并密封)。我可以在应用程序引导程序中批量初始化我的所有类,然后不进行进一步的动态类创建就将类加载器搁置一旁。

对于像我这样的场景,合适的策略是什么?

1 个答案:

答案 0 :(得分:1)

使用WRAPPER策略创建的类加载器允许稍后在类加载器的生命周期中加载类。出于安全原因,需要通过在策略上调用opened()来启用此功能。

然后您可以将第一个类加载器强制转换为InjectionClassLoader,从而允许使用InjectionClassLoader.Strategy.INSTANCE,其中可以注入其他类而无需任何不安全的API。

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