【问题标题】:How to make Byte Buddy load many types into the same wrapper class loader如何让 Byte Buddy 将多种类型加载到同一个包装类加载器中
【发布时间】:2019-08-27 09:59:42
【问题描述】:

我在可能需要使用它创建数万个类的场景中使用 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中是否有更好的机制来做到这一点。

请注意,为了有一个正确密封的类加载器,我可以将我所有的数千个 DynamicType.Unloaded 对象一次性转换为 Class&lt;?&gt; 一个单一的类加载器实例(并密封它)。我可以在应用程序引导程序中批量初始化我的所有类,然后不理会类加载器,而无需进一步创建动态类。

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 再次感谢您。此外,API 将 unsealed 类加载器描述为可以通过任何获取类加载器实例的引用来“破坏包封装”。您能否举例说明“破坏包封装”的含义?我正在尝试评估“opened()”类加载器可能给我带来的风险......
    • 很乐意提供帮助。如果您生成的代码具有包私有成员,任何人都可以将新类注入打开的类加载器并访问这些成员。
    猜你喜欢
    • 1970-01-01
    • 2017-08-19
    • 2014-09-19
    • 2012-01-20
    • 2019-02-15
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    相关资源
    最近更新 更多