【问题标题】:A custom system class loader is not used by all classes并非所有类都使用自定义系统类加载器
【发布时间】:2012-05-01 23:20:28
【问题描述】:

我正在实现一个功能,该功能需要在多个 JVM 实例之间(通过网络)传递动态生成的类型(以二进制表示,用 Kryo 序列化)。为了正确解析加载了哪些类型,哪些没有加载,我使用了自定义系统类加载器(作为 java -Djava.system.class.loader 参数传递),其他动态创建的类加载器将其用作父类。这个自定义系统类加载器知道它的子类,如果它找不到一个类,可以询问这些派生类加载器是否有它(这与类加载器的标准层次结构相反)。

这些动态生成的类型可以完美地在不同的 JVM 之间传输和加载。当我尝试反序列化引用动态生成的类型之一的某种类型的实例(从磁盘加载相应的类并且对于所有 JMV 都是相同的)时,就会出现问题——ClassNotFoundException 由 Kryo 的实例引发,它试图readClass 按动态生成类型的名称。

在方法readClass 中调用Class.forName,它不使用指定的自定义类加载器(知道所有动态生成的类型),而是使用sun.misc.Launcher$AppClassLoader 实例。

是否可以指定一个自定义的系统范围的类加载器,以便所有类都加载它以避免所描述的问题?


更新

进一步分析发现ClassLoader.getSystemClassLoader()实际上返回了指定的自定义系统类加载器。幸运的是,Kryo 库支持设置自定义类加载器,专门用于在反序列化时加载类。这两个事实构成了解决所描述问题的基础。

【问题讨论】:

    标签: java dynamic-class-loaders


    【解决方案1】:

    如果所有类都必须使用该类加载器加载,您将如何加载自定义类加载器?

    解决此问题的一种方法是创建本机检测代理。这是在加载任何类之前加载的。

    另一种解决方法是编译您自己的 AppClassLoader 版本并将其作为引导类路径的前缀或将其添加到 libs/endorsed 目录。

    【讨论】:

    • 当然……我只是希望 JVM 会分析需要加载的最少类以加载 java.system.class.loader 本身,然后用它加载所有其余部分。感谢您的建议。
    • 我相信它假设您不会更改最小的类集,因此不需要重新加载它们。
    • 它们不需要重新加载,但它们的实例可能会开始引用动态加载的多态兼容类型的实例,因此无法使用在序列化期间加载的默认类找到它们/反序列化过程。是否有关于类加载、本机检测代理和自定义 AppClassLoader 实现主题的权威参考资料? JVM规范?谢谢。
    猜你喜欢
    • 2014-10-18
    • 2017-04-09
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多