2012-12-05 15 views
6

In Java, la serializzazione rende la lettura e la scrittura di oggetti negli stream DAVVERO facile. Per esempio, il seguente frammento di codice è in gran parte tutto quello che serve per scrivere gli oggetti in un flusso:Trova percorso alla variabile membro non serializzabile

ObjectOutputStream oos = ... //Initialize your output stream 
Object toWrite = ...   //Initialize what you want to write here 
oos.writeObject(toWrite); //Writes the object to the stream 
oos.flush(); 

questo funzionerà bene, a condizione che toWrite 's classe implementa l'interfaccia Serializable, e che tutti toWrite' s le variabili membro non transient sono anche Serializable. In altre parole, l'intera gerarchia dell'oggetto che si sta tentando di inviare tramite il riferimento toWrite deve essere Serializable. Supponiamo che l'unico problema con questo codice sia che qualcosa all'interno di toWrite non sia Serializable.

Se la gerarchia non è completamente Serializable, la chiamata a oos.writeObject(toWrite) genera un java.io.NotSerializableException. Tutto questo va bene e bene, tranne che l'eccezione non ti dà abbastanza tutto il necessario per risolvere il problema rapidamente. Ti dirà quale classe non può essere serializzata. Il tuo stack trace potrebbe essere simile a questo:

java.io.NotSerializableException: some.package.and.ClassIDidntExplicitlyReference 
    at java.io.ObjectOutputStream.writeObject0(Unknown Source) 
    ... 
    at my.package.MyClass.codeThatWroteTheOffendingObject(MyClass.java:###) 

Questa sorta di voi punti nella giusta direzione, ma in casi che coinvolgono gerarchie di oggetti profonde a cui fa riferimento toWrite, non è sempre chiaro dove il riferimento di classe incriminata è venuto da. Diciamo che assegno toWrite a un'istanza di MyClass e che la mia istanza di MyClass abbia un membro Riferimento oggetto chiamato nonSerializableReference che è stato impostato su un'istanza di ClassIDidntExplicitlyReference, che non è Serializable. Mi piacerebbe vedere qualcosa di simile a quanto segue stampato fuori:

my.package.MyClass.nonSerializableReference instanceof some.package.and.ClassIDidntExplicitlyReference 

So che questo problema probabilmente non ha una soluzione rapida, ed è probabile che comportano l'uso Riflessioni. Qualcuno qui su SO ha fatto questo prima e in caso affermativo, ti dispiacerebbe condividere la tua intuizione?

risposta

ho finito per usare la riflessione Field e Modifier classe per trovare il percorso. Sfortunatamente, non posso condividere il mio codice (contro la politica aziendale), ma posso mostrarti il ​​mio risultato. Classe A detiene un'istanza di B, B detiene un'istanza di C, e C detiene un'istanza di D. Tutti sono Serializable tranne D. Ho finito per usare Depth-First-Search per trovare il percorso:

A.b -> 
    B.c -> 
    C.d instanceof class D 

Se effettuo il transitorio C.d, la ricerca non produce risultati. Molto carino!

+0

Si desidera modificare l'implementazione della serializzazione Java, cercare alcune altre implementazioni come la serializzazione JBoss, forse quella che ha richiesto o inviare una richiesta sulla comunità Java Oracle .... –

+0

Non penso che capiate cosa sono sto chiedendo Non voglio cambiare l'implementazione della serializzazione, voglio semplicemente sapere il percorso da 'myObject' alla variabile membro che ha causato il problema. Dopodiché, deciderei come rendere tale variabile membro implementare 'Serializable' o renderlo' transient'. * Quella * decisione dipende totalmente da ciò che il percorso verso la variabile incriminata finisce per essere. – CodeBlind

+0

'Funziona anche se non si hanno loop di serializzazione': non è corretto. La serializzazione affronta perfettamente i grafi degli oggetti ciclici. Vedi la Specifica di serializzazione dell'oggetto. – EJP

risposta

2

Questa è una domanda strana: stai cercando di determinare in fase di esecuzione cosa dovresti fare in fase di compilazione. In teoria, il percorso dell'oggetto non dovrebbe essere lo - è necessario trovare gli oggetti che fanno riferimento a elementi che non sono serializzabili per correggere il codice.

Detto questo, è possibile scrivere un semplice crawler ricorsivo utilizzando la riflessione. Detto questo, si potrebbe essere in grado di cavarsela con l'implementazione del proprio ObjectInputStream che registra gli oggetti che arrivano in modo appropriato. Consiglio di dare un'occhiata allo source per maggiori dettagli

+1

D'accordo, è strano, ma a volte non è sempre ovvio al momento della compilazione cosa potrebbe non essere serializzabile. Fondamentalmente sto scrivendo un framework di calcolo distribuito che molti sviluppatori porteranno su una base di codice molto grande, complessa e vecchia da usare. Alcune delle gerarchie oggetto di cui si occuperanno sono molto profonde e il modo più rapido per trovare i problemi di serializzazione è eseguirlo e vedere cosa succede. Ho un sistema di log che sa quando si verificano NotserializableExceptions, quindi sarà responsabile della stampa del percorso verso gli oggetti che causano le eccezioni. – CodeBlind

2

Ho avuto lo stesso problema e ho implementato anche la cosa crawler di cui hai parlato.Se qualcuno è ancora interessato in esso, ho presentato il codice qui: A good way to find unserializable fields in Java

+0

Dato che questo fornisce un'implementazione utilizzabile (che ho appena usato con buoni risultati, grazie!), Questa dovrebbe essere la risposta accettata. –

4

passare il flag -Dsun.io.serialization.extendedDebugInfo=true alla JVM e dovrebbe dare la esattamente le informazioni desiderate, quando un NotSerializableException viene generata.

Problemi correlati