オブジェクトをシリアル化し、ネットワーク経由で転送します。シリアル化されたクラス オブジェクトには、自分で定義した serilizableId があります。別の JVM では、SeriliazibleId を同じに保ちますが、いくつかの属性を変更します。何が起こるのか、なぜですか?デシリアライズできますか?
質問する
56 次
2 に答える
1
Java Object Serialization Specification を参照する必要があります。
具体的には、あなたがしてはいけないこと:
- フィールドの削除 - クラスでフィールドが削除された場合、書き込まれたストリームにはその値が含まれません。ストリームが以前のクラスによって読み取られると、ストリームで使用できる値がないため、フィールドの値はデフォルト値に設定されます。ただし、このデフォルト値は、以前のバージョンが契約を履行する能力を損なう可能性があります。
- クラスを階層の上または下に移動 - ストリーム内のデータが間違った順序で表示されるため、これは許可されません。
- 非静的フィールドを静的に変更するか、非一時フィールドを一時的に変更する - デフォルトのシリアル化に依存している場合、この変更はクラスからフィールドを削除することと同じです。このバージョンのクラスはそのデータをストリームに書き込まないため、以前のバージョンのクラスで読み取ることはできません。フィールドを削除する場合と同様に、以前のバージョンのフィールドはデフォルト値に初期化されるため、予期しない方法でクラスが失敗する可能性があります。
- プリミティブ フィールドの宣言された型の変更 - クラスの各バージョンは、宣言された型でデータを書き込みます。ストリーム内のデータの型がフィールドの型と一致しないため、フィールドを読み取ろうとする以前のバージョンのクラスは失敗します。
- writeObject メソッドまたは readObject メソッドを変更して、デフォルト フィールド データの書き込みまたは読み取りを行わないようにするか、以前のバージョンでは書き込みまたは読み取りが試行されなかったときに書き込みまたは読み取りを試行するように変更します。デフォルトのフィールド データは、一貫してストリームに表示されるか、表示されない必要があります。
- クラスを Serializable から Externalizable に、またはその逆に変更することは、互換性のない変更です。ストリームには、使用可能なクラスの実装と互換性のないデータが含まれるためです。
- 利用可能なクラスの実装と互換性のないデータがストリームに含まれるため、クラスを非列挙型から列挙型に、またはその逆に変更します。
- Serializable または Externalizable を削除すると、古いバージョンのクラスで必要なフィールドが提供されなくなるため、互換性のない変更になります。
- writeReplace メソッドまたは readResolve メソッドをクラスに追加しても、その動作によって古いバージョンのクラスと互換性のないオブジェクトが生成される場合、互換性がありません。
代わりにできること:
- フィールドの追加 - 再構成中のクラスに、ストリームには存在しないフィールドがある場合、オブジェクト内のそのフィールドは、そのタイプのデフォルト値に初期化されます。クラス固有の初期化が必要な場合、クラスは、フィールドをデフォルト以外の値に初期化できる readObject メソッドを提供する場合があります。
- クラスの追加 - ストリームには、ストリーム内の各オブジェクトのタイプ階層が含まれます。ストリーム内のこの階層を現在のクラスと比較すると、追加のクラスを検出できます。オブジェクトを初期化するための情報がストリームにないため、クラスのフィールドはデフォルト値に初期化されます。
- クラスの削除 - ストリーム内のクラス階層を現在のクラスのクラス階層と比較すると、クラスが削除されたことを検出できます。この場合、そのクラスに対応するフィールドとオブジェクトがストリームから読み取られます。プリミティブ フィールドは破棄されますが、削除されたクラスによって参照されるオブジェクトは、後でストリーム内で参照される可能性があるため、作成されます。ストリームがガベージ コレクションまたはリセットされると、それらはガベージ コレクションされます。
- writeObject/readObject メソッドの追加 - ストリームを読み取るバージョンにこれらのメソッドがある場合、readObject は、通常どおり、デフォルトのシリアライゼーションによってストリームに書き込まれた必要なデータを読み取ることが期待されます。オプションのデータを読み取る前に、まず defaultReadObject を呼び出す必要があります。writeObject メソッドは、通常どおり defaultWriteObject を呼び出して必要なデータを書き込み、その後、オプションのデータを書き込むことが期待されます。
- writeObject/readObject メソッドの削除 - ストリームを読み取るクラスにこれらのメソッドがない場合、必要なデータはデフォルトのシリアル化によって読み取られ、オプションのデータは破棄されます。
- java.io.Serializable の追加 - これは型の追加と同じです。このクラスのストリームには値がないため、そのフィールドはデフォルト値に初期化されます。シリアル化できないクラスのサブクラス化をサポートするには、クラスのスーパータイプに引数なしのコンストラクターが必要であり、クラス自体がデフォルト値に初期化されます。引数なしのコンストラクターが使用できない場合、InvalidClassException がスローされます。
- フィールドへのアクセスの変更 - アクセス修飾子 public、package、protected、および private は、フィールドに値を割り当てるシリアライゼーションの機能には影響しません。
- フィールドを静的から非静的に、または一時的に非一時的に変更する - デフォルトのシリアル化に依存してシリアル化可能なフィールドを計算する場合、この変更はクラスにフィールドを追加することと同じです。新しいフィールドはストリームに書き込まれますが、シリアル化では静的フィールドまたは一時フィールドに値が割り当てられないため、以前のクラスでは値が無視されます。
于 2013-10-03T17:12:14.367 に答える