java - 如何使用自定义类加载器反序列化对象?
问题描述
在一个项目中,我需要使用自定义类加载器扩展标准类加载器。这样做的主要动机是在运行时扩展类路径。(有关此问题的解决方案,请参阅:https ://stackoverflow.com/a/51584718/231397 )。
通过序列化对象
ObjectOutputStream out;
try {
FileOutputStream fos = new FileOutputStream(filename);
out = new ObjectOutputStream(fos);
out.writeObject(object);
}
catch(FileNotFoundException e) {}
catch (IOException e) { }
finally {
out.close();
}
工作正常,同时通过反序列化对象
Object object = null;
ObjectInputStream in;
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fis);
object = in.readObject();
}
catch(FileNotFoundException e) {}
catch (ClassNotFoundException e) {}
finally {
in.close();
}
失败但有ClassNotFoundException
异常。原因是调用了标准类加载器,不知道自定义类加载器。
问:使用自定义类加载器反序列化对象的正确方法是什么?
解决方案
(注意:在网上搜索了解决方案后,我对自己的问题给出了答案。在网上找到的一些解决方案“几乎正确”:它不适用于内部类)。
解决方案是扩展ObjectInputStream
和覆盖该方法resolveClass(ObjectStreamClass)
这可以通过匿名类来完成。然后Class.forName
在内部resolveClass
使用自定义类加载器。那是
Object object = null;
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream in = new ObjectInputStream(fis) {
@Override
public Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
try {
return Class.forName(desc.getName(), true, customClassLoader);
} catch (Exception e) { }
// Fall back (e.g. for primClasses)
return super.resolveClass(desc);
}
};
object = in.readObject();
}
catch(FileNotFoundException e) {}
catch (ClassNotFoundException e) {}
finally {
in.close();
}
备注:您可能会找到建议使用的解决方案
customClassLoader.loadClass(desc.getName());
代替
Class.forName(desc.getName(), true, customClassLoader)
虽然这在许多情况下可能有效,但它可能存在问题。例如,我发现它customClassLoader.loadClass(desc.getName())
不适用于内部类(可能是由于包 p 中解析为 pAB 或 pA$B 的类 A 的内部类 B 的命名不同)。另请注意,loadClass
不初始化类。见https://stackoverflow.com/a/7099453/231397
推荐阅读
- renjin - 线程“主”org.renjin.eval.EvalException 中的异常:无法解析包“dplyr”中的本机方法“dplyr_combine_vars”
- angular - 如何在 Angular 6 中使用多个视图
- python-3.x - 使用 Pool 时出现 EOF 错误
- matlab - 在 MATLAB 中存储和绘制两个结构体
- laravel - Laravel Vue - 如何让 vue 在公共文件夹中查找图像
- ios - 使用 SnapKit 约束动画
- codeigniter - Codeigniter form_open_multipart 显示 403 Forbidden (CSRF)
- java - 运行 mvn 时合并速度模板时出错
- ruby-on-rails - 如何合并两个 ActiveRecord 对象,包括关联
- r - 根据值将逗号分隔的数字列拆分为多列