2009-08-24 12 views
18

C'è un modo per determinare lo serialVersionUID generato di un oggetto Java serializzato?Ricerca di serialVersionUID dell'oggetto serializzato

Il problema è che ho serializzato un oggetto senza specificare esplicitamente lo serialVersionUID. Ora il processo di deserializzazione si lamenta delle incompatibilità di classe. Tuttavia non ho cambiato la classe in un modo che lo renderebbe incompatibile. Quindi presumo che sia sufficiente specificare lo serialVersionUID nella classe così come è memorizzato nei dati dell'oggetto. Per fare questo ho bisogno di leggere il serialVersionUID dai dati serializzati.

+0

Cosa succede nel caso in cui un metodo viene aggiunto alla classe? L'oggetto serializzato più vecchio può essere letto usando la classe serializzata modificata? – sprezzatura

+0

I metodi non costituiscono lo stato di un oggetto, quindi nessun problema con la lettura dell'oggetto serializzato a meno che non si utilizzi alcun serialVersionUID. –

risposta

12

È possibile farlo estendendo 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(); 
    } 

} 

Credo che sarebbe stato possibile leggere tutti i dati serializzati sostituendo il descrittore restituito dal metodo, ma non ho provato.

0

Questo è esattamente quello che dovresti fare: specifica il tuo static final long serialVersionUID.

C'è una sezione al riguardo nei documenti per Serializable.

A meno che non abbia specificato un serialVersionUID Non credo che ci sia un modo semplice per ottenerlo diverso dalla decifrazione dello stream come suggerisce @WMR.

+0

Si noti che deve essere denominato serialVersionUID (not: serialversionuid - Java fa distinzione tra maiuscole e minuscole) e dovrebbe essere privato statico finale lungo). – Jesper

+0

Sono d'accordo. Ma c'è un modo per leggere l'UID generato dai dati serializzati? – paweloque

5

Esistono metadati associati ai bit serializzati (un'intestazione se lo si desidera). Puoi leggere il valore dai metadati se sai in quale posizione è (lo SerialVersionUID è scritto lì insieme ad altre informazioni come il nome della classe).

Penso che questo articolo possa essere d'aiuto: The Java serialization algorithm revealed.

Si noti che i bit sono scritti "in chiaro" (a meno che non si sia crittografato il flusso esplicitamente), quindi un editor HEX potrebbe essere tutto ciò che serve per vedere che cos'è lo SerialVersionUID.

21

C'è un modo semplice per scoprire serialVersionUID di un classe-

Supponiamo di avere classe in cui si è dimenticato di menzionare serialversionUID-

import java.io.Serializable; 

public class TestSerializable implements Serializable { 

} 

Basta fare questo-

serialver -classpath . TestSerializable 

Questa stampa-

static final long serialVersionUID = 5832063776451490808L; 

serialver è un programma di utilità che viene con JDK

+2

Ma questo funziona solo se si ha la vecchia versione della classe TestSerializable. Il problema di lewap è che non sa quale sia il valore di serialVersionUID con una vecchia versione della classe dell'oggetto che ha serializzato. Se non ha più la vecchia versione della classe, non può usare il serialver per scoprirlo. – Jesper

+0

è a cosa serve il controllo della versione. – james

13

Questo funziona per me:

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

Spero che ti aiuta troppo.

0

c'è modo molto più semplice per ottenere il serialVersionUID di oggetto serializzato - basta deserializzare con Commons apache serializzazione utils per stessa classe con la versione di serie diverso uid e leggere il messaggio di eccezione che sarà più o meno:

org.apache.commons.lang.SerializationException: java.io.InvalidClassException: my.example.SerializableClass; classe locale incompatibili: flusso classdesc serialVersionUID = -1, classe locale serialVersionUID = -2

0

enter image description here per gli sviluppatori di Android,

è anche possibile abilitare l'ispezione serializzazione da Impostazioni -> Editor -> Ispezioni -> abilitare "Classe serializzabile senza 'serialVersionUID' verifica" prima, quindi ALT + INVIO, lo studio creerà serialVersionUID per te.

Problemi correlati