2013-04-18 20 views
7

Esiste un modo esplicito per impedire a ProGuard di modificare una classe dall'implementazione di un'interfaccia?Come impedire a ProGuard di rimuovere l'interfaccia Serializable da una classe

Ho una classe che implementa java.io.Serializable, chiamiamolo com.my.package.name.Foo. Ho scoperto che dopo aver attraversato ProGuard, non implementa più Serializable. Ottengo null dopo aver lanciato da Serializable a Foo e false se controllo un'istanza con instanceof Serializable. Ho fatto in modo di impostare ProGuard di ignorare questa classe:

-keep class com.my.package.name.Foo 

Ho anche provato:

-keep class com.my.package.name.Foo { *; } 

e ho provato anche l'intero pacchetto in questo modo:

-keep class com.my.package.name.** { *; } 

o:

-keep class com.my.package.** { *; } 

e anche solo per mantenere tutte le classi Serializable:

-keep class * implements java.io.Serializable { *; } 

ma senza alcun risultato. Ho un'altra classe in un pacchetto fratello (circa: com.my.package.name2.Bar) che implementa anche Serializable e viene utilizzata allo stesso modo ma non presenta problemi.

Non sono sicuro che sia rilevante, ma lo sto imballando in un barattolo per l'utilizzo con Android. Il codice che utilizza queste classi include inserirli in Bundle s, motivo per cui ho bisogno di Serializable. Ho pensato che forse in qualche modo ProGuard pensa che Foo non sia mai usato come Serializable ma sembra improbabile dato che lo passo come parametro a Bundle.putSerializable(String, Serializable) e faccio anche un cast implicito: Serializable serializable = foo;. Infatti, quando eseguo il debug, posso vedere il Foo immettersi nel Bundle e posso esaminare il Bundle e vedere l'istanza di Foo lì, ma quando lo si recupera il cast fallisce.

risposta

4

ProGuard non elimina mai le interfacce definite nelle librerie (come Serializable) dalle classi nel codice elaborato (come Foo). Il codice della libreria può essere trasmesso a tali interfacce, quindi non possono essere rimossi.

ottengo nulla dopo aver gettato da Serializable Foo

Ciò significa che l'istanza deve essere nullo per iniziare. La tua analisi sarebbe corretta se ricevessi una ClassCastException. È possibile controllare che Foo implementi ancora Serializable con javap. Il problema probabilmente sta altrove. Per suggerimenti sulla serializzazione, è possibile consultare il manuale di ProGuard> Esempi>Processing serializable classes.

Aggiornamento:

In questo caso, si rivela essere un problema di configurazione. ProGuard può elaborare solo i file di classe se conosce tutto sulla loro gerarchia (proprio come un compilatore).È veramente a indicare le classi di runtime:

-libraryjars <java.home>/lib/rt.jar 

o per Android:

-libraryjars /usr/local/android-sdk/platforms/android-17/android.jar 

L'Android Ant/Eclipse costruisce specificare automaticamente tutte le necessarie -injars/-outjars/-libraryjars opzioni per voi, ma in un processo di compilazione personalizzato, devi specificarli tu stesso. Cfr. Manuale di ProGuard> Esempi>A complete Android application.

Si noti che l'opzione -dontwarn cancella gli avvisi, ma non i problemi. Usalo solo se davvero necessario.

+0

Grazie per l'input, ma ho controllato con '' javap' e foo' non implementa più 'Serializable'. Il tuo commento su 'ClassCastException' ha senso anche per me, ma non sembra funzionare in questo modo. Il mio sospetto è che sia accaduto qualcosa nella riduzione e nell'ottimizzazione per cambiare il comportamento da ciò che potreste aspettarvi dal normale codice Java, poiché a quel punto non è più Java, ma codice byte. – kabuko

+0

Ho scoperto che se ho ProGuard impostato su '-dontshrink' e quindi uso esplicitamente' -keep, allowoptimization, allowhrinking, allowobfuscation Foo' allora 'Foo' implementerà ancora' Serializable', ma sfortunatamente non è una soluzione per me come mi piacerebbe restringere in generale. – kabuko

+0

Se si dispone di un piccolo esempio che illustra il problema, lo esaminerò. È possibile trovare il mio indirizzo e-mail nella pagina dei commenti del sito Web ProGuard. –

21

Ho risolto lo stesso problema utilizzando la configurazione di seguito.

-keepnames class * implements java.io.Serializable 
-keepclassmembers class * implements java.io.Serializable { 
    static final long serialVersionUID; 
    private static final java.io.ObjectStreamField[] serialPersistentFields; 
    !static !transient <fields>; 
    private void writeObject(java.io.ObjectOutputStream); 
    private void readObject(java.io.ObjectInputStream); 
    java.lang.Object writeReplace(); 
    java.lang.Object readResolve(); 
} 

Documentazione ufficiale http://proguard.sourceforge.net/manual/examples.html#serializable

+2

Documentazione: http://proguard.sourceforge.net/manual/examples.html#serializable – shkschneider

+1

A mio parere, questa dovrebbe essere una regola predefinita in proguard. – nilsmagnus

+0

Grazie! Ho passato così tanto tempo a cercare di farlo funzionare. – Eduard