Enable Multidex in Android Application

To understand Android 65k method limit, let us first understand the basic (a simple way) of how an android apk is built.

android_apk_build_process.png
  • As shown in the graph, aapt (Android Asset Packaging Tool) collects all the XML files like AndroidManifest file and generate R.java file.
  • R.java file, Java classes + .aidl files are sent to Java Compiler to create .class files (bytecodes).
  • These class files along with class files of external libraries are sent to Dalvik Compiler to create dex files (dalvik executables).
  • These dex files along with other resources like images, audio or video are sent to android package builder to create an apk file, which is then signed and released.

The Dalvik VM imposes a limitation on number of methods that can be referenced in a single dex file. The standard limitation is that you can have a maximum of 65,536 method references in a single dex file. This is famously known as Android 65k method limit.

So, when your app and the libraries it references exceed 65,536 methods, you encounter a build error that indicates your app has reached the limit of the Android build architecture.

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

Older versions of the build system report a different error, which is an indication of the same problem:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

Both these error conditions display a common number: 65536. This number represents the total number of references that can be invoked by the code within a single Dalvik Executable (DEX) bytecode file. This article explains how to move past this limitation by enabling an app configuration known as multidex, which allows your app to build and read multiple DEX files.

Android app (APK) files contain executable bytecode files in the form of Dalvik Executable (DEX) files, which contain the compiled code used to run your app. The Dalvik Executable specification limits the total number of methods that can be referenced within a single DEX file to 65,536 - including Android framework methods, library methods, and methods in your own code.

Versions of the platform prior to Android 5.0 (API level 21) use the Dalvik runtime for executing app code. By default, Dalvik limits apps to a single classes.dex bytecode file per APK. In order to get around this limitation, you can add the multidex support library to your project. This library becomes part of the primary DEX file of your app and then manages access to the additional DEX files and the code they contain.

Android 5.0 (API level 21) and higher uses a runtime called ART which natively supports loading multiple DEX files from APK files. ART performs pre-compilation at app install time which scans for classesN.dex files and compiles them into a single .oat file for execution by the Android device. Therefore, if your minSdkVersion is 21 or higher, you do not need the multidex support library.

Setting up your app project to use a multidex configuration requires that you make the following modifications to your app project, depending on the minimum Android version your app supports.

If your minSdkVersion is set to 21 or higher, all you need to do is set multiDexEnabled to true in your module-level build.gradle file, as shown here:

android {
    defaultConfig {
        ...
        minSdkVersion 21
        targetSdkVersion 26
        multiDexEnabled true
    }
    ...
}

However, if your minSdkVersion is set to 20 or lower, then you must use the multidex support library as follows.

Modify the module-level build.gradle file to enable multidex and add the multidex library as a dependency, as shown here:

android {
    defaultConfig {
        ...
        minSdkVersion 15
        targetSdkVersion 26
        multiDexEnabled true
    }
    ...
}

dependencies {
    ...
    compile 'com.android.support:multidex:1.0.1'
}

Depending on whether you override the Application class, perform one of the following.

If you do not override the Application class, edit your manifest file to set android:name in the <application> tag as follows:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application
            android:name="android.support.multidex.MultiDexApplication" >
        ...
    </application>
</manifest>

If you do override the Application class, change it to extend MultiDexApplication (if possible) as follows:

public class MyApplication extends MultiDexApplication { ... }

Or if you do override the Application class but it's not possible to change the base class, then you can instead override the attachBaseContext() method and call MultiDex.install(this) to enable multidex:

public class MyApplication extends SomeOtherApplication {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}

Now when you build your app, the Android build tools construct a primary DEX file (classes.dex) and supporting DEX files (classes2.dex, classes3.dex, and so on) as needed. The build system then packages all DEX files into your APK.

You can count methods per-package via dex-method-counts.