2013-04-18 2 views
7

ProGuard에서 클래스를 인터페이스 구현에서 변경하지 않으려는 명확한 방법이 있습니까?ProGuard에서 클래스에서 Serializable 인터페이스를 제거하지 못하도록하는 방법

나는 java.io.Serializable을 구현하는 클래스를 가지고 있는데, com.my.package.name.Foo이라고 부르기로한다. ProGuard를 실행 한 후에는 더 이상 Serializable을 구현하지 않습니다. 내가 instanceof Serializable으로 인스턴스를 확인하면 Serializable에서 Foofalse으로 전송 한 후에 을 얻습니다.

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

나는 또한 시도했다 : :이 클래스 무시 ProGuard에서 설정되어 있는지 확인했습니다

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

을 나는이 수행하여 전체 패키지를 시도했다 :

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

나 :

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

모든 Serializable 클래스를 계속 유지하는 것 :

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

그러나 아무 소용이 없습니다. 나는 형제 패키지 (대략 : com.my.package.name2.Bar)에 또 다른 클래스를 가지고 있는데 이것도 Serializable을 구현하며 비슷하게 사용되지만 문제는 없다.

관련성이 확실하지 않지만 Android에서 사용하기 위해 항아리에 포장하고 있습니다. 이러한 클래스를 사용하는 코드는 Bundle에 넣는 것을 포함하므로 Serializable이 필요합니다. 나는 아마도 ProGuard가 FooSerializable으로 사용 된 적이 없다고 생각하지만 아마도 Bundle.putSerializable(String, Serializable)에 대한 매개 변수로 이것을 전달할 가능성이 희박하며 암시 적 캐스트 : Serializable serializable = foo;을 수행한다고 생각했습니다. 사실, 내가 디버그 할 때, Bundle에 들어가서 Foo을 볼 수 있고 거기에서 Bundle을 검사 할 수 있고 Foo의 인스턴스를 볼 수 있습니다.하지만이를 검색 할 때 캐스트가 실패합니다.

답변

4

ProGuard는 Foo와 같이 처리되는 코드의 클래스에서 라이브러리 (예 : Serializable)에 정의 된 인터페이스를 제거하지 않습니다. 라이브러리 코드가 해당 인터페이스로 전송 될 수 있으므로 제거 할 수 없습니다. 나는이 인스턴스로 시작하는 null이어야한다는 것을 의미

Foo 등을 직렬화에서 주조 후

내가 널 얻을. ClassCastException이 발생하면 분석이 정확합니다. Foo가 여전히 Serializable을 javap으로 구현하는지 확인할 수 있습니다. 문제는 아마 다른 곳에있다. 직렬화에 대한 팁은 ProGuard 매뉴얼> 예>Processing serializable classes을 참조하십시오.

업데이트 :이 경우

, 그것은 구성 문제로 밝혀졌습니다. ProGuard는 (컴파일러처럼) 계층 구조에 대한 모든 것을 알고있는 경우에만 클래스 파일을 처리 할 수 ​​있습니다.

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

또는 안드로이드 : 당신은 정말 런타임 클래스를 지정해야

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

안드로이드 개미/이클립스 자동으로 당신을 위해 필요한 모든 -injars/-outjars/-libraryjars 옵션을 지정 빌드를하지만, 사용자 정의 빌드 프로세스에서 직접 지정해야합니다. Cfr. ProGuard 설명서> 예>A complete Android application.

-dontwarn 옵션을 사용하면 경고가 사라지지만 문제는 해결되지 않습니다. 정말로 필요한 경우에만 사용하십시오.

+0

감사합니다,하지만 난 Foo' 더 이상'Serializable'를 구현하지 않는'javap''으로 확인하고했습니다. 'ClassCastException'에 대한 여러분의 의견도 나에게 의미가 있지만, 그렇게 작동하지 않는 것 같습니다. 저의 의구심은 정상적인 자바 코드가 자바 코드가 아닌 자바 코드가 아니라 바이트 코드가 될 것으로 기대했던 것과 행동을 바꾸기위한 축소와 최적화에서 어떤 일이 일어났습니다. – kabuko

+0

ProGuard를'-dontshrink'로 설정하고 명시 적으로'-keep, allowoptimization, allowshrinking, allowobfuscation Foo'를 사용하면'Foo'가 여전히'Serializable'을 구현하지만 불행히도 저에게는 해결책이 아니라는 것을 발견했습니다 나는 축소가 일반적으로 이루어지기를 원한다. – kabuko

+0

문제를 설명하는 작은 샘플이있는 경우 살펴 보겠습니다. 내 메일 주소는 ProGuard 웹 사이트의 피드백 페이지에서 찾을 수 있습니다. –

21

다음 설정을 사용하여 동일한 문제가 수정되었습니다.

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

공식 문서 입력에 대한 http://proguard.sourceforge.net/manual/examples.html#serializable

+2

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

+1

제 생각에 이것은 프로 가드의 기본 규칙이었을 것입니다. – nilsmagnus

+0

고마워요! 나는이 일을하기 위해 많은 시간을 보냈습니다. – Eduard

관련 문제