我正在实现一项功能,该功能需要在多个JVM实例(通过网络)之间传递动态生成的类型(以二进制表示形式,使用Kryo序列化)。为了正确解析加载的类型和不加载的类型,我使用自定义系统类加载器(作为java -Djava.system.class.loader
参数传递),其他动态创建的类加载器用作父类。这个自定义系统类加载器知道它的子类,如果它找不到类,可以询问这些派生类加载器是否有它(这与类加载器的标准层次结构相反)。
这些动态生成的类型在不同的JVM之间传输和加载完全正常。当我尝试反序列化某个类型的实例(从磁盘加载相应的类并且对于所有JMV是相同的)引用其中一个动态生成的类型时出现问题 - 由Kryo的实例引发ClassNotFoundException,它试图readClass
按动态生成的类型的名称。
在方法readClass
内调用Class.forName
,而ClassLoader.getSystemClassLoader()
又不使用指定的自定义类加载器(知道所有动态生成的类型),而是使用sun.misc.Launcher $ AppClassLoader实例
是否可以指定一个自定义系统范围的类加载器,以便所有类都加载它以避免所描述的问题?
更新
进一步分析显示{{1}}实际上返回指定的自定义系统类加载器。幸运的是,Kryo库支持设置自定义类加载器,专门用于在反序列化时加载类。这两个事实构成了解决所述问题的基础。
答案 0 :(得分:4)
如果所有类都必须使用该类加载器进行加密,那么如何加载自定义类加载器?
解决此问题的一种方法是创建本机检测代理。这是在加载任何类之前加载的。
另一种方法是编译自己的AppClassLoader版本,并将其作为引导类路径的前缀,或将其添加到libs/endorsed
目录。