ご存知のように、シリアル化されたJavaオブジェクトツリーを逆シリアル化するときは、ツリー内のすべてのクラスがクラスパス上にある必要があります。したがって、誰かがいくつかのクラスを別のパッケージに移動したため、逆シリアル化はClassNotFoundExceptionをスローします。
私の質問は、私自身のシリアル化/逆シリアル化を実装するよりも、これを解決する簡単な方法はありますか?
ご存知のように、シリアル化されたJavaオブジェクトツリーを逆シリアル化するときは、ツリー内のすべてのクラスがクラスパス上にある必要があります。したがって、誰かがいくつかのクラスを別のパッケージに移動したため、逆シリアル化はClassNotFoundExceptionをスローします。
私の質問は、私自身のシリアル化/逆シリアル化を実装するよりも、これを解決する簡単な方法はありますか?
わかりました。この質問はおそらく重複していると思います。以前の投稿に対するスティーブンの答えは私にとってはうまくいきます。他のパッケージに移動されたクラスを逆シリアル化できます。記録のために、ここに使用するObjectInputStreamのサブクラスを配置します。
public class ClassNameMappingObjectInputStream extends ObjectInputStream {
public static Map<String, Class> classNameMapping = initclassNameMapping();
private static Map<String, Class> initclassNameMapping(){
Map<String, Class> res = new HashMap<String, Class>();
res.put("com.lsy.nlm.report.filter.Filter", com.lsy.nlm.filter.Filter.class);
res.put("com.lsy.nlm.report.filter.FilterSummary", com.lsy.nlm.filter.FilterSummary.class);
res.put("com.lsy.nlm.report.filter.TopFilter", com.lsy.nlm.filter.TopFilter.class);
return Collections.unmodifiableMap(res);
}
public ClassNameMappingObjectInputStream(InputStream in) throws IOException {
super(in);
}
protected ClassNameMappingObjectInputStream() throws IOException, SecurityException {
super();
}
@Override
protected java.io.ObjectStreamClass readClassDescriptor()
throws IOException, ClassNotFoundException {
ObjectStreamClass desc = super.readClassDescriptor();
if (classNameMapping.containsKey(desc.getName())){
return ObjectStreamClass.lookup(classNameMapping.get(desc.getName()));
}
return desc;
}
}
上記の Stephen C によるクラス記述子の変更に関するリンクがおそらく最適だと思います。数か月前に、似たようなものを実装しなければならなかったときにそれを知っていたらよかったのにと思います。
私の場合、元のクラスが非常に進化して元の構造を反映しなくなったため、うまくいくかどうかはわかりませんが、それを機能させるには舞台裏で多くの大工仕事が必要だったでしょう。
いずれにせよ、最近、同様の問題を解決する必要がありました。私の場合、移行クラスを作成しました。その中で、セカンダリクラスローダーを使用して古いバージョンのクラス (元のパッケージにあるもの) をロードし、それらを使用してシリアル化されたオブジェクトの情報を抽出し、それをそれらの新しいバージョン (新しいパッケージにあるもの) にコピーしました。パッケージ構造)。残念ながら、このコピーは、2 つの別個のクラス ローダーを使用していたため、ある程度の Java リフレクションがないと実行できませんでした。