运行签名的Android应用程序,NPE发生,可能是由于proguard?

时间:2014-05-24 19:57:33

标签: java android proguard

我有一个我一直在开发的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,所以我有点偏离了我的元素。

有人可以建议我如何进一步调试吗?

1 个答案:

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