バージョン トレラント ストレージのクラス構造に柔軟性を持たせるために、Java シリアライゼーション メカニズムのさまざまなオプションを調査しています (別のメカニズムを提唱しています。教えていただく必要はありません)。
たとえば、下位互換性のみが必要な場合、デフォルトのシリアル化メカニズムはフィールドの追加と削除の両方を処理できます。
ただし、クラスの名前を変更したり、別のパッケージに移動したりすることは、はるかに難しいことがわかっています。この質問で、ObjectInputStream をサブクラス化し、readClassDescriptor() をオーバーライドすることで、単純なクラスの名前変更および/またはパッケージの移動を実行できることがわかりました。
if (resultClassDescriptor.getName().equals("package.OldClass"))
resultClassDescriptor = ObjectStreamClass.lookup(newpackage.NewClass.class);
単純な名前変更には問題ありません。しかし、フィールドを追加または削除しようとすると、java.io.StreamCorruptedException が発生します。さらに悪いことに、これは、フィールドが追加または削除された後にクラスの名前を変更した場合でも発生します。これにより、複数の開発者または複数のチェックインで問題が発生する可能性があります。
私が行ったいくつかの読書に基づいて、名前を新しいクラスに正しく再指定しているが、古いクラス自体をロードせず、フィールドの変更を爆撃していないという考えで、resolveClass() のオーバーライドも少し試しました。しかし、これは、シリアライゼーション メカニズムの詳細についての非常に漠然とした理解に由来するものであり、正しいツリーをほえているかどうかさえわかりません。
だから2つの正確な質問:
- readClassDescriptor() を使用してクラス名を再指定すると、互換性のある通常のクラス変更で逆シリアル化が失敗するのはなぜですか?
- resolveClass() または別のメカニズムを使用してこれを回避し、クラスの進化 (フィールドの追加と削除) と名前の変更/再パッケージ化の両方を可能にする方法はありますか?
私はぶらぶらして、SOで同等の質問を見つけることができませんでした。どうしても、そのような質問があれば教えてください。しかし、別の質問が私の正確な質問に実際に答えない限り、私を閉じないように、質問を注意深く読んでください。