逆シリアル化の問題の原因は何ですか?
質問に答える前に、少し背景を説明したいと思います。
シリアル化ランタイムは、シリアル化されたオブジェクトの送信者と受信者がシリアル化に関して互換性のあるそのオブジェクトのクラスをロードしたことを確認するために逆シリアル化中に使用される、serialVersionUIDと呼ばれるバージョン番号を各シリアル化可能なクラスに関連付けます。受信者が、対応する送信者のクラスとは異なるserialVersionUIDを持つオブジェクトのクラスをロードした場合、逆シリアル化すると、InvalidClassExceptionが発生します。
シリアル化可能なクラスがserialVersionUIDを明示的に宣言していない場合、シリアル化ランタイムは、クラスのさまざまな側面に基づいて、そのクラスのデフォルトのserialVersionUID値を計算します。クラスの次の情報を使用してSerialVersionUIDを計算します。
- クラス名。
- 32ビット整数として記述されたクラス修飾子。
- 名前でソートされた各インターフェースの名前。
- フィールド名でソートされたクラスの各フィールド(プライベート静的フィールドとプライベート一時フィールドを除く:
- フィールドの名前。
- 32ビット整数として記述されたフィールドの修飾子。
- フィールドの記述子。
-
クラス初期化子が存在する場合は、以下を書き出します。
メソッドの名前。
メソッドの修飾子、java.lang.reflect.Modifier.STATIC、32ビット整数として記述されています。
メソッドの記述子、()V。
-
メソッド名とシグネチャでソートされた非プライベートコンストラクターごとに:
メソッドの名前。
32ビット整数として記述されたメソッドの修飾子。
メソッドの記述子。
-
メソッド名とシグネチャでソートされた非プライベートメソッドごとに:
メソッドの名前。
32ビット整数として記述されたメソッドの修飾子。
メソッドの記述子。
だから、あなたの質問に答えるために、
公的/私的財産の削除は問題を引き起こしますか?おそらく、新しいプロパティを追加しますか?クラスに新しい関数を追加すると問題が発生しますか?もっとコンストラクターはどうですか?
はい、デフォルトでこれらすべての追加/削除により問題が発生します。
しかし、これを克服する1つの方法は、SerialVersionUIDを明示的に定義することです。これにより、クラスが時間の経過とともに進化する(または進化する)ことがわかっており、エラーがスローされないことがシリアル化システムに通知されます。したがって、逆シリアル化システムは、両側に存在するフィールドのみを読み取り、値を割り当てます。デシリアライズ側に新しく追加されたフィールドは、デフォルト値を取得します。デシリアライズ側で一部のフィールドが削除された場合、アルゴリズムは読み取りとスキップを行うだけです。
以下は、SerialVersionUIDを宣言する方法です。
private static final long serialVersionUID = 3487495895819393L;