質問

Java では、静的フィールドと一時フィールドはシリアル化されません。ただし、静的フィールドを初期化すると、生成されたserialVersionUIDが変更されることがわかりました。例えば、 static int MYINT = 3; これにより、serialVersionUID が変更されます。この例では、クラスのバージョンが異なれば初期値も異なるため、これは当然のことです。初期化によってserialVersionUIDが変更されるのはなぜですか?例えば、 static String MYSTRING = System.getProperty("foo"); また、serialVersionUID も変更されます。

具体的に言うと、私の質問は、メソッドによる初期化によって、serialVersionUID が変更されるのはなぜなのかということです。私が遭遇した問題は、システム プロパティ値 (getProperty) で初期化された新しい静的フィールドを追加したことです。この変更により、リモート呼び出しでシリアル化例外が発生しました。

役に立ちましたか?

解決

それに関する情報は、 バグ 4365406 そしてその中で コンピューティングのためのアルゴリズム シリアルバージョンUID. 。基本的に、初期化を変更するときは、 static メンバーと System.getProperty(), 、コンパイラは新しいものを導入します static を参照するクラス内のプロパティ System クラス( System クラスは以前はクラス内で参照されていませんでした)、コンパイラによって導入されたこのプロパティはプライベートではないため、 serialVersionUID 計算。

道徳:常に明示的なものを使用する serialVersionUID, 、CPU サイクルと頭痛の種をいくつか節約できます :)

他のヒント

自動のserialVersionUIDは、クラスのメンバーに基づいて計算されます。これらは、Sun JDK の javap ツールを使用してクラス ファイルに対して表示できます。

質問で述べたケースでは、追加/削除されるメンバーは静的初期化子です。これは、クラス ファイルでは ()V として表示されます。メソッドの内容は、javap -c を使用して逆アセンブルできます。System.getProperty("foo") の呼び出しと MYSTRING への割り当てを理解できるはずです。ただし、文字列リテラル (または Java 言語仕様で定義されているコンパイル時定数) による代入はクラス ファイルによって直接サポートされているため、静的初期化子は必要ありません。

J2SE 1.4 (-source 1.4 -target 1.4 を使用) 以前をターゲットとするコードの一般的なケースは、ソース コード (MyClass.class) でクラス リテラルとして表示される古い Class インスタンスへの静的フィールドです。Class インスタンスは、Class.forName を使用してオンデマンドで検索され、静的フィールドに保存されます。SerialVersionUID を混乱させるのはこの静的フィールドです。J2SE 5.0 以降、ldc オペコードのバリアントによりクラス リテラルが直接サポートされ、合成フィールドが不要になりました。繰り返しますが、これらすべては javap -c で表示できます。

仕様を正しく読めば、自動的に serialVersionUID 一時フィールドの静的な値を変更しても、変更されるべきではありません。を見てみましょう 5.6章 仕様の

しかし, これについて少し考えてみると、まず、次のようなオブジェクトをシリアル化することから始めます。 static int MYINT = 3, 、その後、クラスを逆シリアル化すると、同じオブジェクトが返されることが期待されます。 MYINT = 3. 。したがって、静的初期化を変更すると、次のことが期待されます。 serialVersionUID 同じオブジェクトを再び取得することはできないため、変更する必要があります。

いずれかの方法, 、これをすべてのシリアル化可能なクラスに保持すると、 serialVersionUID:

private static final long serialVersionUID = 7526472295622776147L;

より明確になるように質問を更新しました。リテラルで初期化すると変更される理由がわかりました serialVersionUID しかし、動的初期化によって変更される理由は不明です。メソッドで初期化する場合、当然のことながら、値は常に異なる可能性があります。

の設定 serialVersionUID 安全な変更であると確信できる場合にのみ、クラスの後続のバージョンで明示的に問題ありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top