0

I have an android app I have been developing, and it's now ready to launch. It works great running from eclipse unsigned. When I export a signed copy and run it, an NPE occurs. I've tried creating the signed version with the latest supplied proguard files (proguard-android.txt and proguard-android-optimize.txt). No difference with either. The only mods I've made via my local proguard config file is to leave line numbers so I can get a decent stack trace.

The NPE is what has me scratching my head. I use a lock object for synchronization, and I initialize it in the definition of the object and also during stream initialization:

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

In my debugging version, lock is never null, but in my signed version, when I go to use the lock object, it's null, consistently. I can only assume proguard is doing something I don't want, but this is the first time I've delved into proguard so I'm a bit out of my element.

Can anyone suggest how I can debug this further?

mvsjes2
  • 1,254
  • 2
  • 14
  • 23
  • Do you serialize this `HttpRequest` object in any way? If so, [this question](http://stackoverflow.com/q/12324472/1079354) may be worth a read/duplicate. – Makoto May 24 '14 at 20:03
  • @Makoto but shouldn't that be independent of obfuscation? – matiash May 24 '14 at 20:17

1 Answers1

1

Proguard does three things: shrink, optimize, obfuscate.

In the shrink step, it cuts out any unused program code. What may be happening to you is that Proguard may be stripping away the readObject method because it appears to be unused. I would expect there to be a keep-rule for that method out of the box, but apparently there isn't, or at least not in the Android SDK.

One way to verify that would be to assemble your app with -dontobfuscate in the proguard config, then extracting the classes.dex file from the APK package and running dexdump classes.dex and looking for the presence or absence of the readObject method.

Ultimately, to ensure the readObject method is preserved, you would add the following rule to your ProGuard config:

-keepclassmembers class * implements java.io.Serializable {
  private void readObject(java.io.ObjectInputStream);
}

Updated by mvsjes2 to add the config that actually worked for me:

-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();
}
mvsjes2
  • 1,254
  • 2
  • 14
  • 23
Barend
  • 17,296
  • 2
  • 61
  • 80
  • Thank you barend! When I tried your solution it improved things but the problem moved on to something else stream related. I updated the answer with the config that worked for me, taken from the proguard site. – mvsjes2 May 25 '14 at 15:34