我有一个我一直在开发的Android应用程序,现在它已经准备好了。从eclipse unsigned运行起来很棒。当我导出签名副本并运行它时,会发生NPE。我尝试使用最新提供的proguard文件(proguard-android.txt和proguard-android-optimize.txt)创建签名版本。两者都没有区别。我通过本地proguard配置文件制作的唯一mod是留下行号,这样我就可以得到一个不错的堆栈跟踪。
NPE让我摸不着头脑。我使用锁对象进行同步,并在对象的定义中以及在流初始化期间初始化它:
public class HttpRequest extends NetworkRequest {
private transient Object lock = new Object();
<snip>
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
lock = new Object();
}
在我的调试版本中,lock永远不会为null,但在我的签名版本中,当我使用锁定对象时,它始终为null。我只能假设proguard正在做一些我不想要的事情,但这是我第一次深入研究proguard,所以我有点偏离了我的元素。
有人可以建议我如何进一步调试吗?
答案 0 :(得分:1)
Proguard做了三件事:缩小,优化,混淆。
在缩小步骤中,它会删除任何未使用的程序代码。可能发生的事情是Proguard可能正在剥离readObject
方法,因为它似乎未使用。我希望开箱即用该方法的保留规则,但显然没有,或者至少没有在Android SDK中。
一种验证方法是在proguard配置中使用-dontobfuscate
汇总您的应用,然后从APK包中提取classes.dex文件并运行dexdump classes.dex
并查找是否存在readObject
方法。
最终,为确保保留readObject
方法,您需要将以下规则添加到ProGuard配置中:
-keepclassmembers class * implements java.io.Serializable {
private void readObject(java.io.ObjectInputStream);
}
由mvsjes2更新以添加实际适用于我的配置:
-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();
}