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

From ProGuard to R8: take care of your byte code

jinqian
April 23, 2018

From ProGuard to R8: take care of your byte code

jinqian

April 23, 2018
Tweet

More Decks by jinqian

Other Decks in Technology

Transcript

  1. Agenda • ProGuard in Android Build Process • Why ProGuard?

    • ProGuard Essentials • Understand the default ProGuard settings • ProGuard like a Pro • What do we know about R8? • Takeaways
  2. ProGuard is a open source Java class file shrinker, optimizer,

    obfuscator, and preverifier, created by Eric Lafortune, initially released in May 2002, latest version 6.0 was released in February 2018
  3. Obfuscation public class ExampleClass { private MySettings settings; private MyConfigurations

    configurations; private int result; private int calculateResult(int input) { // ... return result; } } public class a { private b a; private c b; private int c; private int a(int a) { // ... return c; } } Input jars Shrunk code Optimized code Obfuscated code Output jars
  4. Reference: https://android-developers.googleblog.com/2017/08/next-generation-dex-compiler-now-in.html App source code (*.java or *.kt) JAR Library

    bytecode (*.class) AAR Library bytecode (*.class) App Java bytecode (*.class) javac / kotlinc ProGuard / R8 Optimized Java bytecode (*.class) DEX bytecode (*.dex) DX / D8 * D8 is the default DEX compiler in Android Studio 3.1 release * R8 is available for test starting from Android Studio 3.2 alpha 6
  5. Reference: https://android-developers.googleblog.com/2017/08/next-generation-dex-compiler-now-in.html App source code (*.java or *.kt) JAR Library

    bytecode (*.class) AAR Library bytecode (*.class) App Java bytecode (*.class) javac / kotlinc ProGuard / R8 Optimized Java bytecode (*.class) DEX bytecode (*.dex) DX / D8 ProGuard Inputs (Rules) ProGuard Outputs (dump.txt, mapping.txt, seeds.txt, usage.txt)
  6. Streamline Your Application! • Resource shrinking • Smaller APK size

    • Smaller download size • Smaller DEX size Reference: https://en.wikipedia.org/wiki/We_Can_Do_It!
  7. Debug (Without ProGuard, minifyEnabled=false, shrinkResources=false) Release (With ProGuard, minifyEnabled=true, shrinkResources=true)

    APK Size 30.7 MB 23.5 MB* Dex Method Count 151,235 109,634** Without/With ProGuard Reference: https://github.com/mihaip/dex-method-counts *app size is 30% smaller ** dex count is reduced by 37% v3.26.2
  8. -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); }

    Entry Point Example Reference: https://www.guardsquare.com/en/proguard/manual/usage#classspecification Keep Option Class Specification
  9. Reference: https://www.guardsquare.com/en/proguard/manual/usage#keepoverview From being removed or renamed From being renamed

    (Short for -keep,allowshrinking) -keep -keepnames -keepclassmembers -keepclassmembernames -keepclasseswithmembers -keepclasseswithmembernames
  10. proguard-android.txt @Keep annotation # Understand the @Keep support annotation. -keep

    class android.support.annotation.Keep -keep @android.support.annotation.Keep class * {*;} -keepclasseswithmembers class * { @android.support.annotation.Keep <methods>; } -keepclasseswithmembers class * { @android.support.annotation.Keep <fields>; } -keepclasseswithmembers class * { @android.support.annotation.Keep <init>(...); }
  11. /app/build.gradle Generated by default buildTypes { release { proguardFiles getDefaultProguardFile(

    'proguard-android.txt'), 'proguard-rules.pro' } } ➡ This does nothing!
  12. /app/build.gradle Enable code shrinking buildTypes { release { minifyEnabled true

    proguardFiles getDefaultProguardFile( 'proguard-android.txt'), 'proguard-rules.pro' } } ➡ minifyEnabled shrinks the code with the default proguard rules
  13. /app/build.gradle Enable code & resource shrinking buildTypes { release {

    minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile( 'proguard-android.txt'), 'proguard-rules.pro' } }
  14. /app/build.gradle Enable code optimization buildTypes { release { minifyEnabled true

    shrinkResources true proguardFiles getDefaultProguardFile( 'proguard-android-optimize.txt'), 'proguard-rules.pro' } } ➡ Optimization is turned off by default. ➡ Dex does not like code run through the ProGuard optimization steps.
  15. /app/build.gradle Shrink code for Instant Run Reference: https://developer.android.com/studio/build/shrink-code.html#gradle-shrinker buildTypes {

    debug { minifyEnabled true useProguard false proguardFiles getDefaultProguardFile( 'proguard-android.txt'), 'proguard-rules.pro' } }
  16. MagritteModel.kt version 1.0 Reference: https://github.com/xebia-france/magritte package fr.xebia.magritte.model data class MagritteModel(val

    id: String, val name: String, val description: String, val configuration: MagritteConfiguration)
  17. proguard.pro version 1.0 -keep class fr.xebia.magritte.model.** {*;} -dontwarn okio.** -dontwarn

    javax.annotation.** -keepclasseswithmembers class * { @com.squareup.moshi.* <methods>; } -keep @com.squareup.moshi.JsonQualifier interface *
  18. MagritteModel.kt version 2.0 Reference: https://github.com/xebia-france/magritte package fr.xebia.magritte.model import android.os.Parcelable import

    com.squareup.moshi.Json import kotlinx.android.parcel.Parcelize @Parcelize data class MagritteModel( @Json(name = "id") val id: String, @Json(name = "name") val name: String, @Json(name = "description") val description: String, @Json(name = "model_file_path") val modelFilePath: String, @Json(name = "model_type") val modelType: TFModelType, @Json(name = "configuration") val configuration: MagritteConfiguration ) : Parcelable
  19. proguard.pro version 2.0 Reference: https://github.com/square/moshi/issues/345 -keep class kotlin.Metadata { *;

    } -keepclassmembers class kotlin.Metadata { public <methods>; } -keep class fr.xebia.magritte.model.** {*;} -dontwarn okio.** -dontwarn javax.annotation.** -keepclasseswithmembers class * { @com.squareup.moshi.* <methods>; } -keep @com.squareup.moshi.JsonQualifier interface *
  20. Reference: https://speakerdeck.com/takhion/unleash-the-secret-power-of-kotlin-metadata k -> kind mv -> meta data version

    bv -> byte code version d1 -> data 1 d2 -> data 2 xs -> extra string xi -> extra int
  21. When to use -dontwarn? Example: Retrofit2 complains about can’t find

    annotation classes javax.annotation.Nullable (from JSR 305) Reference: https://medium.com/google-developers/troubleshooting-proguard-issues-on-android-bce9de4f8a74
  22. What we know about R8? • R8 & D8 share

    the same code base • R8 is a ProGuard replacement for whole-program optimization, shrinking and minification. • R8 uses the same ProGuard keep rule format & command line arguments • R8 implements different optimisations than ProGuard • R8 supports Instant Run*(?) • Available from Android Studio 3.2 alpha 6 • Build faster than ProGuard & decrease dex file size by 34% for some app** *Reference: https://developer.android.com/studio/build/shrink-code.html#gradle-shrinker **Reference: http://androidbackstage.blogspot.fr/2018/01/episode-86-its-gr8.html
  23. R8 Benchmarks * Magritte: https://github.com/xebia-france/magritte ** Tested with Android Studio

    3.2 alpha 11 Magritte* Release (ProGuard without optimization) Release (R8** without optimization) Release (ProGuard with optimization) Release (R8** with optimization) APK Size 22.1MB 23.2MB 23MB 23MB Dex Count 25758 23199 (-10%) ? Build Time 52s 57s
  24. R8 Benchmarks * Magritte: https://github.com/xebia-france/magritte ** Tested with Android Studio

    3.2 alpha 11 Magritte* Release (ProGuard without optimization) Release (R8** without optimization) Release (ProGuard with optimization) Release (R8** with optimization) APK Size 22.1MB 23.2MB 23MB 23MB Dex Count 25758 23199 (-10%) 21527 18039 (-16.2%) Build Time 52s 57s 2m16s 55s (2.5x faster)
  25. R8 Benchmarks * Plaid: https://github.com/nickbutcher/plaid by Nick Butcher ** Tested

    with Android Studio 3.2 alpha 11 Plaid* Release (ProGuard with optimization) Release (R8** with optimization) APK Size 6.8MB 6.7MB Dex Count 19049 16460 (-14%) Build Time 1m49s 36s (2.75x faster)
  26. Takeways • Read the source Luke • Read the byte

    code too Luke • Exception log is your friend • Dex decompiler is also your friend • Commercialized alternative: DexGuard Reference: https://blog.codinghorror.com/learn-to-read-the-source-luke/
  27. Takeways • Consumer ProGuard file for your AAR library •

    Test with ProGuard • ProGuard for Instant App • …