3

We've recently decided to disable code obfuscation in our Android build, since while it makes the final APK slightly larger, it makes debugging so much more difficult.

Ever since we've done that, I keep running into crashes in our app that were not present before, i.e. while obfuscation was still active. Usually these crashes are caused by Java VerifyErrors or NoSuchMethodErrors.

Here are two of these errors I suddenly see when I disable obfuscation:

Could not find method org.apache.http.HttpConnectionMetrics.getResponseCount, referenced from method com.google.android.apps.analytics.PipelinedRequester.sendRequests
W/dalvikvm( 6652): VFY: unable to resolve virtual method 16112: Lorg/apache/http/HttpConnectionMetrics;.getResponseCount ()J
W/dalvikvm( 6652): VFY:  rejecting opcode 0x6e at 0x000c
W/dalvikvm( 6652): VFY:  rejected Lcom/google/android/apps/analytics/PipelinedRequester;.sendRequests ()V
W/dalvikvm( 6652): Verifier rejected class Lcom/google/android/apps/analytics/PipelinedRequester;
D/dalvikvm( 6652): GC_CONCURRENT freed 253K, 46% free 3261K/6023K, external 0K/0K, paused 2ms+2ms
I/dalvikvm( 6652): Rejecting re-init on previously-failed class Lcom/google/android/apps/analytics/PipelinedRequester; v=0x4062de30
D/AndroidRuntime( 6652): Shutting down VM
W/dalvikvm( 6652): threadid=1: thread exiting with uncaught exception (group=0x400a7560)
E/AndroidRuntime( 6652): FATAL EXCEPTION: main
E/AndroidRuntime( 6652): java.lang.VerifyError: com/google/android/apps/analytics/PipelinedRequester
... 

I could resolve this error by disabling class merging via !class/merging/*

Another error I was seeing was this:

I/dalvikvm( 7292): DexOpt: access denied from Lcom/urbanairship/analytics/EventUploadManager; to field Lorg/apache/http/entity/AbstractHttpEntity;.contentEncoding
W/dalvikvm( 7292): VFY: unable to resolve instance field 5188
D/dalvikvm( 7292): VFY: replacing opcode 0x5b at 0x00ec
I/dalvikvm( 7292): Could not find method org.apache.http.conn.scheme.PlainSocketFactory.<init>, referenced from method com.google.android.apps.analytics.PipelinedRequester.<init>
W/dalvikvm( 7292): VFY: unable to resolve direct method 15044: Lorg/apache/http/conn/scheme/PlainSocketFactory;.<init> (B)V
D/dalvikvm( 7292): VFY: replacing opcode 0x70 at 0x0003
D/dalvikvm( 7292): VFY: dead code 0x0006-0009 in Lcom/google/android/apps/analytics/PipelinedRequester;.<init> (Lorg/apache/http/HttpHost;)V
I/dalvikvm( 7292): DexOpt: access denied from Lcom/google/android/apps/analytics/PipelinedRequester; to field Lorg/apache/http/impl/SocketHttpClientConnection;.open
W/dalvikvm( 7292): VFY: unable to resolve instance field 5234
D/dalvikvm( 7292): VFY: replacing opcode 0x55 at 0x0006
D/dalvikvm( 7292): VFY: dead code 0x0008-000e in Lcom/google/android/apps/analytics/PipelinedRequester;.closeConnection ()V
D/dalvikvm( 7292): VFY: dead code 0x0010-0011 in Lcom/google/android/apps/analytics/PipelinedRequester;.closeConnection ()V
I/dalvikvm( 7292): DexOpt: access denied from Lcom/google/android/apps/analytics/PipelinedRequester; to field Lorg/apache/http/impl/SocketHttpClientConnection;.open
W/dalvikvm( 7292): VFY: unable to resolve instance field 5234
D/dalvikvm( 7292): VFY: replacing opcode 0x55 at 0x0006
D/dalvikvm( 7292): VFY: dead code 0x0008-0009 in Lcom/google/android/apps/analytics/PipelinedRequester;.addRequest (Lorg/apache/http/HttpEntityEnclosingRequest;)V
D/dalvikvm( 7292): GC_CONCURRENT freed 253K, 47% free 3251K/6023K, external 0K/0K, paused 2ms+3ms
I/dalvikvm( 7292): DexOpt: access denied from Lcom/google/android/apps/analytics/PipelinedRequester; to field Lorg/apache/http/impl/AbstractHttpClientConnection;.metrics
W/dalvikvm( 7292): VFY: unable to resolve instance field 5225
D/dalvikvm( 7292): VFY: replacing opcode 0x54 at 0x0008
D/dalvikvm( 7292): VFY: dead code 0x000a-0090 in Lcom/google/android/apps/analytics/PipelinedRequester;.sendRequests ()V
D/AndroidRuntime( 7292): Shutting down VM
W/dalvikvm( 7292): threadid=1: thread exiting with uncaught exception (group=0x400a7560)
E/AndroidRuntime( 7292): FATAL EXCEPTION: main
E/AndroidRuntime( 7292): java.lang.NoSuchMethodError: org.apache.http.conn.scheme.PlainSocketFactory.<init>

This one I could resolve by setting !method/propagation/*

But why do these problems only appear with obfuscation disabled? Shouldn't one have no impact on the other?

mxk
  • 43,056
  • 28
  • 105
  • 132
  • One peculiarity I noticed it that all errors I was seeing involved classes from Apache HttpClient. Maybe I'm headed in the wrong direction? – mxk Jul 06 '12 at 16:07

1 Answers1

4

The obfuscation was saving you because it was renaming your copies of the Apache HttpClient classes to names that wouldn't collide with the copies of those classes already present in Android.

Nasty place to be... you might want to consider not using Apache HttpClient at all, and using the in-built HttpURLConnection class as suggested by Jesse Wilson:

http://android-developers.blogspot.com/2011/09/androids-http-clients.html

You could try this Android-friendly veneer on HttpURLConnection:

https://github.com/kevinsawicki/http-request

If you really have to use Apache HttpClient, either use the old version embedded in Android, or try tweaking your ProGuard configuration to just obfuscate the HttpClient libraries.

Community
  • 1
  • 1
Roberto Tyley
  • 24,513
  • 11
  • 72
  • 101
  • 1
    Hah, that's exactly what the problem was. I actually found out and slapped my forehead before I read your reply. Maven sucked in the Apache Http Components (core and client) as a transitive dependency with compile scope, so ProGuard was adding it as an -injar, not a -libraryjar. The solution was to declare it using provided scope. Thanks! – mxk Jul 09 '12 at 09:49