Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ProGuard

 ProGuard

Slides from Android Tech Talks #9 meetup at @techspacekrk

Jerzy Chalupski

March 12, 2015
Tweet

More Decks by Jerzy Chalupski

Other Decks in Programming

Transcript

  1. $ g assembleDebug
 Total time: 1.908 secs
 
 $ du

    -h ./app-debug.apk
 24K ./app-debug.apk
  2. $ g assembleDebug
 Total time: 3.014 secs
 
 $ du

    -h ./app-debug.apk
 1.8M ./app-debug.apk
  3. $ g assembleDebug
 Total time: 3.014 secs
 
 $ du

    -h ./app-debug.apk
 1.8M ./app-debug.apk $ tar -xzvf app-debug.apk
 
 $ du -h -d 0 classes.dex res
 3.8M classes.dex
 592K res
  4. dependencies {
 compile ‘google-play-services’ compile ‘support.*’ compile ‘guava’ compile ‘gson’

    compile ‘joda-time’ compile ‘square.*’ compile ‘butterknife’ compile ‘rxjava’ compile ‘rxandroid’ compile ‘android-arsenal.*’ }
  5. $ g assembleDebug BUILD SUCCESSFUL 
 Total time: 48.784 secs


    $ du -h ./app-debug.apk
 7.5M ./app-debug.apk
  6. $ g assembleDebug BUILD SUCCESSFUL 
 Total time: 48.784 secs


    $ du -h ./app-debug.apk
 7.5M ./app-debug.apk $ dexcount ./app-debug.apk Total method count: 81986

  7. @Override
 protected void attachBaseContext(Context c) {
 super.attachBaseContext(c);
 long start =

    System.currentTimeMillis();
 MultiDex.install(this);
 long end = System.currentTimeMillis(); long elapsed = end - start;
 Log.d(TAG, “multidex: " + elapsed + "ms");
 }
  8. @Override
 protected void attachBaseContext(Context c) {
 super.attachBaseContext(c);
 long start =

    System.currentTimeMillis();
 MultiDex.install(this);
 long end = System.currentTimeMillis(); long elapsed = end - start;
 Log.d(TAG, “multidex: " + elapsed + "ms");
 } 252ms on Samsung S5 with KitKat at 66k methods
  9. @Override
 protected void attachBaseContext(Context c) {
 super.attachBaseContext(c);
 long start =

    System.currentTimeMillis();
 MultiDex.install(this);
 long end = System.currentTimeMillis(); long elapsed = end - start;
 Log.d(TAG, “multidex: " + elapsed + "ms");
 } 1083ms on Samsung S5 with KitKat at 81k methods
  10. @Override
 protected void attachBaseContext(Context c) {
 super.attachBaseContext(c);
 long start =

    System.currentTimeMillis();
 MultiDex.install(this);
 long end = System.currentTimeMillis(); long elapsed = end - start;
 Log.d(TAG, “multidex: " + elapsed + "ms");
 } ~4000ms on Nexus 5 with KitKat at ~130k methods
  11. @Override
 protected void attachBaseContext(Context c) {
 super.attachBaseContext(c);
 long start =

    System.currentTimeMillis();
 MultiDex.install(this);
 long end = System.currentTimeMillis(); long elapsed = end - start;
 Log.d(TAG, “multidex: " + elapsed + "ms");
 } 2ms on Nexus 5 with Lollipop at 81k methods
  12. buildTypes {
 all {
 minifyEnabled true
 proguardFiles = [
 getDefaultProguardFile(

    ‘proguard-android.txt' ),
 'proguard-rules.pro'
 ]
 }
 }

  13. buildTypes {
 all {
 minifyEnabled true
 proguardFiles = [
 getDefaultProguardFile(

    ‘proguard-android.txt' ),
 'proguard-rules.pro'
 ]
 }
 }

  14. $ANDROID_HOME/tools/proguard/proguard-android.txt --keep class * implements android.os.Parcelable { - public static

    final android.os.Parcelable$Creator *; +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR;
  15. $ANDROID_HOME/tools/proguard/proguard-android.txt --keep class * implements android.os.Parcelable { - public static

    final android.os.Parcelable$Creator *; +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; “OK ProGuard, please keep all Parcelables”
  16. $ANDROID_HOME/tools/proguard/proguard-android.txt --keep class * implements android.os.Parcelable { - public static

    final android.os.Parcelable$Creator *; +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; “OK ProGuard, please keep all *USED* Parcelables”
  17. $ANDROID_HOME/tools/proguard/proguard-android.txt --keep class * implements android.os.Parcelable { - public static

    final android.os.Parcelable$Creator *; +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; http://proguard.sourceforge.net/manual/usage.html
  18. $ dexcount ./app-debug.apk android: 3173
 graphics: 53
 support: 2584
 v4:

    652
 v7: 1932
 internal: 1298
 widget: 621
 view: 201
 widget: 162
  19. $ cat build/ intermediates/ proguard-rules/ debug/ aapt_rules.txt 
 # view

    AndroidManifest.xml #generated:16
 -keep class org.chalup.proguardtechtalk.MainActivity { <init>(...); }
 
 # view res/layout/abc_action_menu_item_layout.xml #generated:17
 -keep class android.support.v7.internal.view.menu.ActionMenuItemView { <init>(...); }
  20. public class MainActivity extends Activity {
 
 @InjectView(R.id.hello_text)
 TextView mTextView;


    
 @Override
 protected void onCreate(Bundle state) {
 super.onCreate(state);
 setContentView(R.layout.activity_main);
 
 ButterKnife.inject(this);
 mTextView.setText(R.string.hello_world);
 }
 }
  21. AndroidRuntime D Shutting down VM E FATAL EXCEPTION: main E

    Process: org.chalup.proguardtechtalk, PID: 21061 E java.lang.RuntimeException: Unable to start activity ComponentInfo{…}: java.lang.NullPointerException: E at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298) E at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) E at android.app.ActivityThread.access$800(ActivityThread.java:144) E at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) E at android.os.Handler.dispatchMessage(Handler.java:102) E at android.os.Looper.loop(Looper.java:135) E at android.app.ActivityThread.main(ActivityThread.java:5221) E at java.lang.reflect.Method.invoke(Native Method) E at java.lang.reflect.Method.invoke(Method.java:372) E at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) E at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) E Caused by: java.lang.NullPointerException: E at org.chalup.proguardtechtalk.MainActivity.onCreate(Unknown Source) E at android.app.Activity.performCreate(Activity.java:5933) E at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) E at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) E ... 10 more
  22. dependencies {
 compile ‘google-play-services’ compile ‘support.*’ compile ‘guava’ compile ‘gson’

    compile ‘joda-time’ compile ‘square.*’ compile ‘butterknife’ compile ‘rxjava’ compile ‘rxandroid’ compile ‘android-arsenal.*’ }
  23. $ g assembleDebug BUILD SUCCESSFUL 
 Total time: 16.096 secs


    $ du -h ./app-debug.apk
 3.5M ./app-debug.apk
  24. $ g assembleDebug BUILD SUCCESSFUL 
 Total time: 16.096 secs


    $ du -h ./app-debug.apk
 3.5M ./app-debug.apk $ dexcount ./app-debug.apk Total method count: 6636

  25. $ g assembleDebug BUILD SUCCESSFUL 
 Total time: 48.784 secs


    $ du -h ./app-debug.apk
 7.5M ./app-debug.apk $ dexcount ./app-debug.apk android.support.v4: 81986

  26. $ g assembleDebug BUILD SUCCESSFUL 
 Total time: 16.096 secs


    $ du -h ./app-debug.apk
 3.5M ./app-debug.apk $ dexcount ./app-debug.apk Total method count: 6636

  27. $ g assembleDebug BUILD SUCCESSFUL 
 Total time: 15.049 secs


    $ du -h ./app-debug.apk
 3.5M ./app-debug.apk $ dexcount ./app-debug.apk Total method count: 6539

  28. -dontobfuscate $ g assembleDebug :app:dexDebug FAILED EXCEPTION FROM SIMULATION: local

    variable type mismatch: Ph'nglui mglw’nafh Cthulhu R'lyeh wgah'nagl fhtagn
  29. LinkedHashMultimap<Integer, String> map =
 LinkedHashMultimap.create(); 
 map.put(1, "1");
 map.put(1, "2");


    map.put(1, "3");
 
 Collection<String> data = map.asMap().get(1);
 Log.d("JCH", new Gson().toJson(data));
  30. E FATAL EXCEPTION: main E Process: org.chalup.proguardtechtalk, PID: 31243 E

    java.lang.reflect.GenericSignatureFormatError E at libcore.reflect.GenericSignatureParser.expect(GenericSignatureParser.java:473) E at libcore.reflect.GenericSignatureParser.parseClassTypeSignature(GenericSignatureParser.java:332) E at libcore.reflect.GenericSignatureParser.parseClassSignature(GenericSignatureParser.java:234) E at libcore.reflect.GenericSignatureParser.parseForClass(GenericSignatureParser.java:126) E at java.lang.Class.getGenericInterfaces(Class.java:1134) E at com.google.gson.internal.$Gson$Types.getGenericSupertype($Gson$Types.java:238) E at com.google.gson.internal.$Gson$Types.getSupertype($Gson$Types.java:269) E at com.google.gson.internal.$Gson$Types.getCollectionElementType($Gson$Types.java:288) E at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:51) E at com.google.gson.Gson.getAdapter(Gson.java:359) E at com.google.gson.Gson.toJson(Gson.java:592) E at com.google.gson.Gson.toJson(Gson.java:579) E at com.google.gson.Gson.toJson(Gson.java:534) E at com.google.gson.Gson.toJson(Gson.java:514) E at org.chalup.proguardtechtalk.MainActivity.getString(MainActivity.java:40) E at org.chalup.proguardtechtalk.MainActivity.onCreate(MainActivity.java:36) E at android.app.Activity.performCreate(Activity.java:5933)
  31. buildscript {
 repositories {
 jcenter()
 }
 dependencies {
 classpath 'com.android.tools.build:gradle:1.0.1'


    }
 configurations.all {
 resolutionStrategy {
 force 'net.sf.proguard:proguard-gradle:4.11'
 }
 }
 }
  32. buildscript {
 repositories {
 jcenter()
 }
 dependencies {
 classpath 'com.android.tools.build:gradle:1.0.1'


    }
 configurations.all {
 resolutionStrategy {
 force 'net.sf.proguard:proguard-gradle:4.11'
 }
 }
 } NOTE: this is top level build.gradle, not module one
  33. @Override
 protected void onCreate(Bundle state) {
 super.onCreate(state);
 setContentView(R.layout.activity_main);
 
 Log.d(TAG,

    doNotRunOnProduction());
 }
 
 private String doNotRunOnProduction() {
 Log.e(TAG, "FIRE ZE MISSILES!");
 
 return "Harmless log message";
 }

  34. @Override
 protected void onCreate(Bundle state) {
 super.onCreate(state);
 setContentView(R.layout.activity_main);
 
 Log.d(TAG,

    doNotRunOnProduction());
 }
 
 private String doNotRunOnProduction() {
 Log.e(TAG, "FIRE ZE MISSILES!");
 
 return "Harmless log message";
 }

  35. @Override
 protected void onCreate(Bundle state) {
 super.onCreate(state);
 setContentView(R.layout.activity_main);
 
 Log.d(TAG,

    doNotRunOnProduction());
 }
 
 private String doNotRunOnProduction() {
 Log.e(TAG, "FIRE ZE MISSILES!");
 
 return "Harmless log message";
 }

  36. @Override
 protected void onCreate(Bundle state) {
 super.onCreate(state);
 setContentView(R.layout.activity_main);
 String tmp

    = doNotRunOnProduction();
 Log.d(TAG, tmp);
 }
 
 private String doNotRunOnProduction() {
 Log.e(TAG, "FIRE ZE MISSILES!");
 
 return "Harmless log message";
 }

  37. @Override
 protected void onCreate(Bundle state) {
 super.onCreate(state);
 setContentView(R.layout.activity_main);
 String tmp

    = doNotRunOnProduction();
 // Log.d(TAG, tmp); pruned by ProGuard
 }
 
 private String doNotRunOnProduction() {
 Log.e(TAG, "FIRE ZE MISSILES!");
 
 return "Harmless log message";
 }

  38. ?