開発者ドキュメント

serialVersionUIDを理解する

The serializable class xxx does not declare a static final serialVersionUID field of type long

だから…​ serialVersionUIDとは何ですか?

serialVersionUIDは、Serializableクラスのバージョンコントロールとして使用されます。 serialVersionUIDを明示的に宣言していない場合、JVMは、http://docs.oracle.com/javase/1.5.0/docs/api/に記載されているように、Serializableクラスのさまざまな側面に基づいて自動的に行います。 java/io/Serializable.html[Java(TM)オブジェクト直列化仕様]

1. SerialVersionUIDの例

上記のステートメントは、最初はわかりにくいです(少なくとも私はそうでした)。Serializableクラスがバージョン管理を実装するためにSerialVersionUIDをどのように使用するかを理解するための例を始めましょう。

1.1 Address.java

serialVersionUIDが1Lの直列化可能クラス。

import java.io.Serializable;

public class Address implements Serializable{

       private static final long serialVersionUID = 1L;

       String street;
       String country;

       public void setStreet(String street){
           this.street = street;
       }

       public void setCountry(String country){
           this.country = country;
       }

       public String getStreet(){
           return this.street;
       }

       public String getCountry(){
           return this.country;
       }

       @Override
       public String toString() {
           return new StringBuffer(" Street : ")
           .append(this.street)
           .append(" Country : ")
           .append(this.country).toString();
       }
}

1.2 WriteObject.java

Addressオブジェクトをファイル “c:\\ address.ser”に書き込み/シリアライズするためのシンプルなクラスです。

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class WriteObject{

    public static void main (String args[]) {

       Address address = new Address();
       address.setStreet("wall street");
       address.setCountry("united states");

       try{

        FileOutputStream fout = new FileOutputStream("c:\\address.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fout);
        oos.writeObject(address);
        oos.close();
        System.out.println("Done");

       }catch(Exception ex){
           ex.printStackTrace();
       }
    }
}

1.3 ReadObject.java

単純なクラスで、ファイル “c:\\ address.ser”からAddressオブジェクトを読み込み/逆シリアル化します。

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ReadObject{

   public static void main (String args[]) {

       Address address;

       try{

           FileInputStream fin = new FileInputStream("c:\\address.ser");
           ObjectInputStream ois = new ObjectInputStream(fin);
           address = (Address) ois.readObject();
           ois.close();

           System.out.println(address);

       }catch(Exception ex){
           ex.printStackTrace();
       }
   }
}

2.テスト

serialVersionUIDの使用方法を示すためにいくつかのテストをしましょう。

2.1同じserialVersionUID

同じserialVersionUID、デシリアライズ処理中は問題ありません

javac Address.java
javac WriteObject.java
javac ReadObject.java
java WriteObject
java ReadObject
Street : wall street Country : united states

2.2異なるserialVersionUID

Address.javaでは、serialVersionUIDを2Lに変更します(1Lでした)。もう一度コンパイルしてください。

javac Address.java
java ReadObject
java.io.InvalidClassException: Address; local class incompatible:
stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
        ...
        at ReadObject.main(ReadObject.java:14)
  • serialVersionUID “1L”

    を使用してシリアライゼーションクラスを作成しますが、更新されたシリアライズクラス

    serialVersionUID “2L” ** を使用してそれを取得しようとするため、 “InvalidClassException”が発生します。

The serialVersionUID have to match during the serialization and
deserialization process.

  • あなたのserialVersionUIDを更新する必要がありますか?** +シリアライズ可能クラスのいくつかの互換性のないJavaタイプの変更でシリアライゼーションクラスが更新されると、serialVersionUIDを更新する必要があります。

シリアライズ可能クラスへの互換性のある互換性のないJavaタイプの変更の詳細は、http://docs.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html[Javaオブジェクトのシリアライズ仕様]を参照してください。

3.デフォルトのserialVersionUIDの何が問題になっていますか?

serialVersionUIDが宣言されていない場合、JVMは独自のアルゴリズムを使用してデフォルトのSerialVersionUIDを生成します。アルゴリズムはhttp://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100で確認できます。[ここに]。

  • デフォルトのserialVersionUIDの計算はクラスの詳細に非常に敏感で、異なるJVM実装** と異なる場合があり、デシリアライズ処理中に予期しないInvalidClassExceptionsが発生する可能性があります。

3.1クライアント/サーバ環境

__クライアントはWindowsでSUNのJVMを使用しています。 – LinuxでJRockitを使用しているサーバー。

クライアントは、デフォルトで生成されたserialVersionUID(例えば123L)を有する直列化可能クラスをソケットを介してサーバに送信し、サーバは直列化解除処理中に異なるserialVersionUID(例えば124L)を生成し、予期しないInvalidClassExceptionsを発生させる。

3.2ファイル/データベース環境


– App#1は、WindowsでSUNのJVMを使用しています。 – App#2はLinuxでJRockitを使用しています.

シリアライゼーションはファイルまたはデータベースに保存できました。 App#2は、直列化可能クラスをデータベースに格納し、デフォルトではserialVersionUID(例えば123L)を生成し、App#2は逆直列化処理中に異なるserialVersionUID(例えば124L)を生成し、予期しないInvalidClassExceptionsを発生させる。

ここでは、http://en.wikipedia.org/wiki/List

of

JVM__implementations[JVM実装の一覧]を確認できます。

4. serialVersionUIDの生成方法

JDKの「serialver」またはEclipse IDEを使用して、自動的にserialVersionUIDを生成することができます。リンク://java/how-to-generate-serialversionuid/[詳細を参照]。

結論

上記の異なるJVMの問題を避けるために、serialVersionUIDを宣言することを強くお勧めしますが、serialVersionUIDがバージョン管理をどのように実装するのか、そしてクラスがシリアル化を使用する必要があるのか​​を理解することをお勧めします。 serialVersionUIDの概念を理解することは、どのような推奨事項にも目をつぶっているよりも優れています。

モバイルバージョンを終了