16

是否有明确的方法来阻止 ProGuard 更改类以实现接口?

我有一个实现的类java.io.Serializable,我们称之为com.my.package.name.Foo。我发现通过 ProGuard 运行后,它不再实现Serializable. 我nullSerializableto 转换后得到Foofalse如果我用instanceof Serializable. 我确保将 ProGuard 设置为忽略此类:

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

我也试过:

-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 使用。使用这些类的代码包括将它们放在Bundles 中,这就是我需要Serializable. 我认为 ProGuard 可能以某种方式认为它Foo从未用作 a Serializable,但考虑到我将它作为参数传递给Bundle.putSerializable(String, Serializable)并且我做了一个隐式转换,这似乎不太可能:Serializable serializable = foo;。事实上,当我调试时,我可以看到Fooget 放入了Bundle,我可以检查Bundle并查看那里的实例Foo,但是在检索它时,强制转换失败。

4

2 回答 2

46

我使用下面的配置解决了同样的问题。

-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

于 2015-05-29T14:49:18.917 回答
5

ProGuard 永远不会从处理的代码中的类(如 Foo)中剥离库中定义的接口(如 Serializable)。库代码可能会转换为这些接口,因此无法删除它们。

从 Serializable 转换为 Foo 后我得到 null

这意味着实例必须为 null 才能开始。如果您得到 ClassCastException,您的分析将是正确的。您可以检查 Foo 是否仍然实现 Serializable with javap。问题可能出在其他地方。有关序列化的提示,您可以查看 ProGuard 手册 > 示例 >处理可序列化类

更新:

在这种情况下,它原来是一个配置问题。ProGuard 只能处理类文件,如果它知道所有关于它们的层次结构(就像编译器一样)。您确实必须指定运行时类:

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

或安卓:

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

Android Ant/Eclipse 构建会自动为您指定所有必要的 -injars/-outjars/-libraryjars 选项,但在自定义构建过程中,您必须自己指定它们。参照。ProGuard 手册 > 示例 >一个完整的 Android 应用程序

请注意,选项 -dontwarn 使警告消失,但不是问题。仅在确实需要时才使用它。

于 2013-04-20T22:42:48.680 回答