Android uses android-support-multidex to solve the problem of Dex exceeding the limit on the number of methods, so that your applications will not burst

Source: Internet
Author: User
Tags jcenter

Android uses android-support-multidex to solve the problem of Dex exceeding the limit on the number of methods, so that your applications will not burst

 

With the continuous iteration of applications and the expansion of business lines, applications become larger and larger (such as integrating various third-party sdks or jar packages supported by the public, with high project coupling and repeated classes ), I believe many people have encountered the following errors:
 

UNEXPECTED TOP-LEVEL EXCEPTION:java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:501)at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:282)at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:490)at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:167)at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:439)at com.android.dx.command.dexer.Main.runMonoDex(Main.java:287)at com.android.dx.command.dexer.Main.run(Main.java:230)at com.android.dx.command.dexer.Main.main(Main.java:199)at com.android.dx.command.Main.main(Main.java:103)

That's right. The number of Dex file methods in your application exceeds the upper limit of 65536. In short, the application burst.

Let's take a look at why this error occurs:

 

InAndroidIn the systemAppAll the code inDexFile.DexIs a Jar-like storage with manyJavaArchive file for compiling bytecode. BecauseAndroidSystem usageDalvikVirtual Machine, so you need to useJava CompilerCompiledClassConvert filesDalvikExecutableClassFile. It should be emphasized that,DexAndJarThe same is an archive file, which is stillJavaThe bytecode file corresponding to the code. WhenAndroidWhen the system starts an application, one step isDexFor optimization, this process has a dedicated tool for processing, calledDexOpt.DexOptIs executed when the Dex file is loaded for the first time. This process generatesODEXFile, that isOptimised Dex. RunODexIs more efficient than direct execution.DexFile efficiency is much higher. However, in the early Android system,DexOptThere is a problem that this article wants to explain and solve.DexOptThe method of each classIdIt is found in a linked list structure. However, the length of the linked list isShortType to save, resulting in the MethodIdThe number cannot exceed65536. When a project is large enough, it is clear that the maximum number of methods is not enough. DespiteAndroidSystem,DexOptThis problem is fixed, but we still needAndroidThe system is compatible.

Currently more commonly used methods :( 1) application plug-ins, such as using the plug-in framework I am involved in the Development: https://github.com/singwhatiwanna/dynamic-load-apk, if you have suggestions or related questions, welcomeGithubActively participate in. (2) splitting Dex, multi-project: Compile the required. class file or Jar file and some source code to generate a Jar file. Then, convert the Jar file into a Dex file using the dx tool provided by the Android SDK. We can perform ODex operations on it in advance so that it can skip part of DexOpt when it is loaded by DexClassLoader to speed up the loading process. these two methods do not conflict. Plug-ins not only solve the application burst, but also have many other advantages. You can refer to my previous articles and do not repeat them.

Of course,GoogleIt seems that we are aware of the explosive growth of application methods.API 21Provides a general solution, that isAndroid-support-multidex.jar. This jar package is supported at leastAPI 4Version (Android LAnd later versions are supported by default.Mutidex).

Let's take a look at how to apply android-support-multidex.jar(The following uses Anroid studio as an example.):

 

You can use -- multi-dex to configure (build. the generated Apk contains multiple dex files, such as classes. dex, classes2.dex. for example. gradle:
afterEvaluate {    tasks.matching {        it.name.startsWith('dex')    }.each { dx ->        if (dx.additionalParameters == null) {            dx.additionalParameters = []        }        dx.additionalParameters += '--multi-dex' // enable multidex        // optional        // dx.additionalParameters += --main-dex-list=$projectDir/
 
  .toString() // enable the main-dex-list    }}
 



However, the default Dalvik Class Loader only looks for classes. dex, so you need to merge them to make them recognized.

Of course, now we have android. support. multidex. jar support makes everything very simple. First, let's take a look at the directory of the relevant source code. The detailed principle analysis will be explained in subsequent articles:
android/support/multidex/BuildConfig.classandroid/support/multidex/MultiDex$V14.classandroid/support/multidex/MultiDex$V19.classandroid/support/multidex/MultiDex$V4.classandroid/support/multidex/MultiDex.classandroid/support/multidex/MultiDexApplication.classandroid/support/multidex/MultiDexExtractor$1.classandroid/support/multidex/MultiDexExtractor.classandroid/support/multidex/ZipUtil$CentralDirectory.classandroid/support/multidex/ZipUtil.class

Specific integration:
Add the following configuration to the project: ClassPathMedium
repositories {  jcenter()}dependencies {  compile 'com.google.android:multidex:0.1'}



There are two steps for integration:

1. Import the android-support-multidex.jar to the project from the sdkextrasandroidsupportmultidexlibrarylibs directory

2. If your project already contains the Application class, let it inherit the android. support. multidex. MultiDexApplication class,

If your Application has inherited other classes and does not want to modify them, there is another way to overwrite the attachBaseContext () method:



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


Finally, complete configuration in build. gradle is provided:
buildscript {    repositories {        jcenter()    }    dependencies {        classpath 'com.android.tools.build:gradle:0.13.3'        classpath 'jp.leafytree.gradle:gradle-android-scala-plugin:1.1'    }}apply plugin: 'com.android.application'apply plugin: 'jp.leafytree.android-scala'repositories {    jcenter()}android {    compileSdkVersion 21    buildToolsVersion '21.0.2'    defaultConfig {        applicationId 'some.app'        minSdkVersion 19        targetSdkVersion 19        versionCode 1        versionName '1.0'    }}dependencies {    compile 'com.google.android:multidex:0.1'    compile 'com.android.support:support-v4:19.0.1'    compile 'com.google.android.gms:play-services:5.0.77'    compile 'org.scala-lang:scala-library:2.11.2'    compile 'org.scaloid:scaloid_2.11:3.4-10'}



MutiDex idea

 

1. If you inherit the MutiDexApplication or overwrite the attachBaseContext () method in the Application.

Considerations for the logic in the Application class:

ApplicationThe static global variables inMutiDexOfInstal ()Method loading is preferred, so we recommend that you do notApplicationClassMain classes. dexThe static variables that may be used in the file can be modified as follows:

@Override    public void onCreate() {        super.onCreate();        final Context mContext = this;        new Runnable() {            @Override            public void run() {                // put your logic here!                // use the mContext instead of this here            }        }.run();    }


FAQs

 

DexException: Library dex files are not supported in multi-dex mode, You may see the following errors:

 

 

Error:Execution failed for task ':app:dexDebug'.> com.android.ide.common.internal.LoggedErrorException: Failed to run command:    $ANDROID_SDK/build-tools/android-4.4W/dx --dex --num-threads=4 --multi-dex    ...  Error Code:    2  Output:    UNEXPECTED TOP-LEVEL EXCEPTION:    com.android.dex.DexException: Library dex files are not supported in multi-dex mode        at com.android.dx.command.dexer.Main.runMultiDex(Main.java:322)        at com.android.dx.command.dexer.Main.run(Main.java:228)        at com.android.dx.command.dexer.Main.main(Main.java:199)        at com.android.dx.command.Main.main(Main.java:103)


 

The -- multi-dex option setting of dex conflicts with the pre-compiled library project. Therefore, if your application contains the referenced lirary project, you need to set the pre-compilation to false:
android {    // ...    dexOptions {        preDexLibraries = false    }}



OutOfMemoryError: Java heap space

If the following error is displayed during running:
UNEXPECTED TOP-LEVEL ERROR:java.lang.OutOfMemoryError: Java heap space

In DexOptionsThere is a field to increase the java heap memory size:
android {    // ...    dexOptions {        javaMaxHeapSize 2g    }}            


References:

1. MutiDex official documentation: Https://developer.android.com/reference/android/support/multidex/MultiDex.html

2.Http://blog.osom.info/2014/10/multi-dex-to-rescue-from-infamous-65536.html
 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.