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

The 65K Dex Limit

berglind
October 11, 2015

The 65K Dex Limit

Only 65.536 method can be invoked in the dex file of android apk. How can we work with it? See presentation at https://www.youtube.com/watch?v=5vEa9dihZEs

berglind

October 11, 2015
Tweet

More Decks by berglind

Other Decks in Technology

Transcript

  1. Unable to execute dex: method ID not in [0, 0xffff]:

    65536 Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536 … becomes hell
  2. • What is this 65K DEX Limit • How to

    “solve” it • What we have been doing at QuizUp I will talk about..
  3. • Android Manifests • Assets folder • Resources folder •

    Some other files • classes.dex Inside APK
  4. The 65K Dex limit • Your app is too big,

    sorry mate! :( • Simple explanation: You have too many methods in the dex file • More specific explanation: You have too many methods (over 65.536 methods), that can being invoked, in the dex file
  5. How to fight this animal Two things you can do:


    A. Cut down the code
 B. Creating multiple Dex files
  6. A. Cut down the code 1. Analyze where the code

    is coming from
 - https://github.com/mihaip/dex-method- counts package com.stupid.dexlimit;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
 
 public class MainActivity extends Activity
 {
 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
 super.onCreate(savedInstanceState);
 helloPeople();
 }
 
 private void helloPeople()
 {
 Log.d(MainActivity.class.getSimpleName(),
 "How many methods are in this Application??");
 }
 }
  7. A. Cut down the code package com.stupid.dexlimit;
 
 import android.app.Activity;


    import android.os.Bundle;
 import android.util.Log;
 
 public class MainActivity extends Activity
 {
 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
 super.onCreate(savedInstanceState);
 helloPeople();
 }
 
 private void helloPeople()
 {
 Log.d(MainActivity.class.getSimpleName(),
 "How many methods are in this Application??");
 }
 } Read in 60307 method IDs. <root>: 60307 : 6 android: 4842 [...] aurelienribon: 99 tweenengine: 99 equations: 22 paths: 5 bolts: 82 butterknife: 36 internal: 7 com: 46491 badlogic: 12414 gdx: 12414 [...] facebook: 3261 [...] [...]
  8. A. Cut down the code 1. Analyze where the code

    is coming from
 - https://github.com/mihaip/dex-method- counts
 - https://github.com/siggijons/dex- methods 
 package com.stupid.dexlimit;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
 
 public class MainActivity extends Activity
 {
 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
 super.onCreate(savedInstanceState);
 helloPeople();
 }
 
 private void helloPeople()
 {
 Log.d(MainActivity.class.getSimpleName(),
 "How many methods are in this Application??");
 }
 }
  9. A. Cut down the code 1. Analyze where the code

    is coming from
 - https://github.com/mihaip/dex-method- counts
 - https://github.com/siggijons/dex- methods 2. Use smaller libraries - Repack libraries with JarJar package com.stupid.dexlimit;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
 
 public class MainActivity extends Activity
 {
 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
 super.onCreate(savedInstanceState);
 helloPeople();
 }
 
 private void helloPeople()
 {
 Log.d(MainActivity.class.getSimpleName(),
 "How many methods are in this Application??");
 }
 }
  10. package com.stupid.dexlimit;
 
 
 public class MainActivity extends Activity
 {


    @Override
 protected void onCreate(Bundle savedInstanceState)
 {
 super.onCreate(savedInstanceState);
 helloPeople();
 }
 
 private void helloPeople()
 {
 Log.d(MainActivity.class.getSimpleName(),
 "How many methods are in this Application??");
 }
 } How many methods are in this example? • 1 Activity w/ 2 methods • Compile the play service library • Question: How many methods are in the APK file? • Answer: ~20.000 methods (1/3 of 65K) • Solution: only compile what you need (e.g. com.google.android.gms:play- services-maps:7.8.0)
  11. A. Cut down the code 1. Analyze where the code

    is coming from
 - https://github.com/mihaip/dex-method- counts
 - https://github.com/siggijons/dex- methods 2. Use smaller libraries - Repack libraries with JarJar 3. Proguard / Dexguard to shrink your code
 pros: Dexguard can shrink quite much
 cons: Increases your build time package com.stupid.dexlimit;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
 
 public class MainActivity extends Activity
 {
 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
 super.onCreate(savedInstanceState);
 helloPeople();
 }
 
 private void helloPeople()
 {
 Log.d(MainActivity.class.getSimpleName(),
 "How many methods are in this Application??");
 }
 }
  12. How to fight this animal Two things you can do:


    A. Cut down the code
 B. Creating multiple Dex files
  13. B. Creating multiple dex files • Normally you can only

    have 1 dex file • Get around this limit by using 3rd party libraries
 - pros: we can build the project
 - cons: longer building time • Mult-Dexing library from Google 
 - com.android.support:support-v4:21.0.0
 - Easy to use • Dexguard offers split dexing
 - splitdexfile com.facebook.**
 - More complex to use with the obfuscation • Today we use Dexguard
  14. Dalvik vs. ART • Difference regarding the dex limit? YES

    • ART (Android 5.0+) contains native support for multidexing • No native support in Dalvik
  15. What we have learned • Dexguard -> Extra complexity level

    for split dexing • Choose what goes to the secondary dex file! • Build can break on run time when certain code is in secondary dex file • Avoid always being on the edge of the limit • Compile time increases, when split dexing :( • The tools for split dexing is becoming much better • Smile :)