2009-08-24 12 views
18

シリアル化されたJavaオブジェクトのserialVersionUIDが生成されたかどうかを判断する方法はありますか?シリアル化されたオブジェクトのserialVersionUIDを見つける

問題は、serialVersionUIDを明示的に指定せずにオブジェクトをシリアライズしたことです。これで、非直列化プロセスでクラスの非互換性が不平等になります。しかし私はそれを互換性のない方法で変更しなかった。だから私はそれがオブジェクトのデータに格納されているようにクラス内のserialVersionUIDを指定するだけで十分だと仮定します。これを行うには、シリアル化されたデータからserialVersionUIDを読み取る必要があります。

+0

メソッドがクラスに追加された場合はどうなりますか?変更されたシリアライズされたクラスを使用して古いシリアル化オブジェクトを読み取ることはできますか? – sprezzatura

+0

メソッドはオブジェクトの状態を構成しないため、serialVersionUIDを使用していない限り、シリアル化されたオブジェクトを読み取る際には問題ありません。 –

答えて

12

あなたはObjectInputStreamを拡張することにより、これを行うことができます。

public class PrintUIDs extends ObjectInputStream { 

    public PrintUIDs(InputStream in) throws IOException { 
    super(in); 
    } 

    @Override 
    protected ObjectStreamClass readClassDescriptor() throws IOException, 
     ClassNotFoundException { 
    ObjectStreamClass descriptor = super.readClassDescriptor(); 
    System.out.println("name=" + descriptor.getName()); 
    System.out.println("serialVersionUID=" + descriptor.getSerialVersionUID()); 
    return descriptor; 
    } 

    public static void main(String[] args) throws IOException, 
     ClassNotFoundException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ObjectOutputStream oos = new ObjectOutputStream(baos); 
    List<Object> list = Arrays.asList((Object) new Date(), UUID.randomUUID()); 
    oos.writeObject(list); 
    oos.close(); 
    InputStream in = new ByteArrayInputStream(baos.toByteArray()); 
    ObjectInputStream ois = new PrintUIDs(in); 
    ois.readObject(); 
    } 

} 

を私はメソッドから返された記述子を交換することにより、すべてのシリアル化されたデータを読み取ることが可能であろうと信じて、私はそれを試していません。

0

これはまさにあなたがすべきことです - あなた自身のstatic final long serialVersionUIDを指定してください。

Serializableのドキュメントには、それに関するセクションがあります。

serialVersionUIDを指定していない限り、@WMRが示唆するようにストリームを解読する以外に簡単な方法はないとは思いません。オブジェクトの直列化のために指定された文法がある

+0

serialVersionUIDという名前でなければなりません(serialversionuidではなくJavaでは大文字と小文字が区別されます)。プライベート静的final longである必要があります)。 – Jesper

+0

私は同意します。しかし、シリアル化されたデータから生成されたuidを読み取る方法はありますか? – paweloque

5

シリアル化されたビット(必要に応じてヘッダー)に関連付けられたメタデータがあります。どの位置にあるかわかっている場合は、メタデータから値を読み取ることができます(SerialVersionUIDがクラス名などの他の情報と共にそこに書き込まれます)。

この記事はあなたに役立つかもしれないと思う:The Java serialization algorithm revealed

ビットは明示的に(ストリームを明示的に暗号化しない限り)書き込まれるため、HEXエディタがSerialVersionUIDの内容を確認するために必要な場合があります。

21

クラス -

のserialVersionUIDのはあなたがちょうどthis-

serialver -classpath . TestSerializable 
を行うserialversionUID-

import java.io.Serializable; 

public class TestSerializable implements Serializable { 

} 

を言及するのを忘れているでクラスを持っていると仮定見つけるための簡単な方法があります

この印刷物 -

static final long serialVersionUID = 5832063776451490808L; 

serialverは、これが私の作品JDK

+2

これは、TestSerializableクラスの古いバージョンを使用している場合にのみ機能します。 lewapの問題は、serialVersionUIDの値が、シリアル化したオブジェクトのクラスの古いバージョンであったかどうかを知らないことです。彼がクラスの古いバージョンをもはや持っていなければ、彼は発見するためにserialverを使うことはできません。 – Jesper

+0

これはバージョンコントロールの対象です。 – james

13

と一緒に来ユーティリティです:

long serialVersionUID = ObjectStreamClass.lookup(YourObject.getClass()).getSerialVersionUID(); 

は、それはあまりにもあなたのお役に立てば幸いです。

0

シリアライズされたオブジェクトのserialVersionUIDのを取得するにははるかに簡単な方法があります - ちょうど別のシリアルバージョンUIDと同じクラスにApacheコモンズのシリアル化utilsのでそれをデシリアライズされ、例外メッセージを読むには多かれ少なかれ:

org.apache.commons.lang.SerializationException:java.io.InvalidClassException:my.example.SerializableClass;互換性のないローカルクラス:Androidの開発者のためのストリームclassdescのserialVersionUID = -1、ローカルクラスのserialVersionUID = -2

0

enter image description here

あなたはまた、設定からシリアライズ検査を有効にすることができます - >エディタ - >検査 - >有効"serialVersionUID 'チェックなしのSerializableクラス、次にAlt + Enterを押すと、スタジオはserialVersionUIDを作成します。

関連する問題