2013-04-18 11 views
7

ProGuard'ın bir sınıfı bir arabirimi uygulamadan değiştirmesini durdurmak için açık bir yol var mı?ProGuard'ın Serializable arabiriminin bir sınıftan çıkarılması nasıl durdurulur

java.io.Serializable'u uygulayan bir dersim var, diyelim ki com.my.package.name.Foo. Ben ProGuard ile koştuktan sonra, artık Serializable uygular. instanceof Serializable ile bir örneği kontrol edersem Serializable'dan Foo ve false'a gönderdikten sonra null'u alırım.

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

Ben de denedim: Ben bu sınıfı görmezden ProGuard ayarlamak için emin yaptık

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

ve ben de bunu yaparak bütün paketi denedim:

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

ya:

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

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

ama boşuna: ve ayrıca sadece tüm Serializable sınıfları tutmak. Kardeş paketinde de (com.my.package.name2.Bar) Serializable'u uygulayan başka bir sınıf var ve benzer şekilde kullanılıyor ancak sorun yok.

Bunun alakalı olduğundan emin değilim, ancak Android ile kullanım için bir kavanozda ambalajlıyorum. Bu sınıfları kullanan kod Bundle s onları koyarak dahil olmak üzere bu yüzden Serializable gerek. Belki de bir şekilde ProGuard'ın Foo'un hiçbir zaman Serializable olarak kullanılmadığını düşündüğüm ama bunun Bundle.putSerializable(String, Serializable) parametresine bir parametre olarak aktardığım ve ayrıca dolaylı bir döküm yapmamın mümkün olmadığını düşündüğümü düşündüm: Serializable serializable = foo;. Aslında, ben hata ayıklama, ben FooBundle içine koymak ve Bundle inceleyebilir ve orada Foo örneğini görebilirsiniz, ancak aldığınızda, döküm başarısız olur.

cevap

4

ProGuard, (Serializable gibi) kitaplıklarda tanımlanmış arabirimleri işlenen (Foo gibi) koddaki sınıflardan ayırmaz. Kütüphane kodu bu arayüzlere yayın yapıyor olabilir, bu yüzden kaldırılamazlar. Ben bu örneği ile başlamak boş olmalıdır anlamına gelir

Foo için Serializable döküm sonrasında

Ben boş olsun. Bir ClassCastException alırsanız analiziniz doğru olur. Foo'nun hala javap ile seri hale getirilebildiğini kontrol edebilirsiniz. Sorun muhtemelen başka bir yerde yatıyor. Serileştirme ile ilgili ipuçları için, ProGuard kılavuzuna> Örnekler>Processing serializable classes bakabilirsiniz.

Güncelleme: Bu durumda

, bir yapılandırma sorunu olarak çıkıyor. ProGuard, hiyerarşisi ile ilgili her şeyi bilirse (sadece bir derleyici gibi) sınıf dosyalarını işleyebilir.

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

veya Android için: Gerçekten çalışma zamanı sınıflarını belirlemek zorunda

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

Android Ant/Eclipse sizin için otomatik olarak gerekli tüm -injars/-outjars/-libraryjars seçenekleri belirtin yapýlar, ancak Özel bir oluşturma işleminde, bunları kendiniz belirtmeniz gerekir. Cfr. ProGuard kılavuzu> Örnekler>A complete Android application.

Bu seçeneğin -dontwarn seçeneğinin uyarıları değiştirdiğine dikkat edin, sorun değil. Sadece gerçekten gerekliyse kullanın.

+0

Teşekkürler ama Foo' artık 'Serializable' uygulamıyor' javap' 'ile kontrol edilip ettik. 'ClassCastException' hakkındaki yorumunuz bana da mantıklı geliyor, ancak bu şekilde çalışmıyor. Şüphelerim şudur ki, küçülme ve optimizasyonda, normal Java kodunun o anda Java değil, bayt kodu olduğu gibi yapmasını beklediğinizden davranışları değiştirmek için bir şey olmuştur. – kabuko

+0

Eğer ProGuard '-dontshrink' olarak ayarlandıysa ve sonra açık bir şekilde '-keep, allowoptimization, allowhrinking, allowobfuscation Foo'yu kullandıktan sonra' Foo'nun 'seri hale getirilebilir 'özelliğini kullanacağını buldum ama maalesef bu benim için bir çözüm değil. Genelde olmak için küçültmek istiyorum. – kabuko

+0

Sorunu gösteren küçük bir örneğiniz varsa, ona bakacağım. Posta adresimi ProGuard web sitesinin Geri Bildirim sayfasında bulabilirsiniz. –

21

Aynı sorun aşağıdaki yapılandırma kullanılarak düzeltildi.

-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(); 
} 

Resmi Belgeler girişi için http://proguard.sourceforge.net/manual/examples.html#serializable

+2

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

+1

Kanımca, bu, proguard'da varsayılan bir kural olmalıydı. – nilsmagnus

+0

Teşekkür ederiz! Bunu çalışmaya çalışmak için çok zaman harcadım. – Eduard