347

I have seen various versions of the dex erros before, but this one is new. clean/restart etc won't help. Library projects seems intact and dependency seems to be linked correctly.

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

or

Cannot merge new index 65950 into a non-jumbo instruction

or

java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

tl;dr: Official solution from Google is finally here!

http://developer.android.com/tools/building/multidex.html

Only one small tip, you will likely need to do this to prevent out of memory when doing dex-ing.

dexOptions {
        javaMaxHeapSize "4g"
}

There's also a jumbo mode that can fix this in a less reliable way:

dexOptions {
        jumboMode true
}

Update: If your app is fat and you have too many methods inside your main app, you may need to re-org your app as per

http://blog.osom.info/2014/12/too-many-methods-in-main-dex.html

Patrick
  • 33,984
  • 10
  • 106
  • 126
Edison
  • 5,961
  • 4
  • 23
  • 39
  • 1
    Do you use api which is not aviable on your currient device? – rekire Mar 04 '13 at 19:47
  • It's there, because another project build fine targeting the same API version. – Edison Mar 04 '13 at 19:50
  • So you use at some point API which is not available? Do you check with a line like `if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)` that you don't call this function if it is not available? – rekire Mar 04 '13 at 19:57
  • Yea, I do. The project built fine before. Also, that should be a runtime error even if I missed the line. – Edison Mar 04 '13 at 20:05
  • It's probably one of the dependencies is messed up. (doing a mix of maven+project lib right now) – Edison Mar 04 '13 at 20:05
  • I have the same problem. Could you tell me how did you solve it? – Lily Mar 05 '13 at 17:50
  • @Edison is it possible that you a) downvoted my answer and b) took a part from it to add to the question as a tip (it really looks like it comparing the time from your edit, and my answer&downvote). Apart from that being a very strange behavior, this is a Q&A site NOT a forum, the answers should NOT be in the question, if you think you have an answer answer your own question and then update it (this is how it should be done) – Patrick Feb 28 '15 at 20:58
  • I added the tip base on my own experience and I didn't downvote your answer, and I did upvote most of the old answers, I didn't upvote yours because I felt you were just trying to summarize the rest of the page but not ideal because people should really just follow the official page. I wouldn't sacrifice a point for that. – Edison Mar 02 '15 at 19:44
  • Also, This is not JUST a Q&A site, this is a site that helps people. So I don't agree on that answers shouldn't be in the question if I believe that more people would find it useful. You don't have to agree with me on this, but I think a lot people do find this helpful and many of the questions are done this way, we all trying to help people better. re: @for3st – Edison Mar 02 '15 at 19:51
  • @Edison dexOptions's jumbo mode has no effect on method indices (though it can help when dex file has too many strings), therefore I'd suggest to remove this to prevent confusion and mislead. – Alex Lipov Mar 08 '16 at 15:52

12 Answers12

379

Update 3 (11/3/2014)
Google finally released official description.


Update 2 (10/31/2014)
Gradle plugin v0.14.0 for Android adds support for multi-dex. To enable, you just have to declare it in build.gradle:

android {
   defaultConfig {
      ...
      multiDexEnabled  true
   }
}

If your application supports Android prior to 5.0 (that is, if your minSdkVersion is 20 or below) you also have to dynamically patch the application ClassLoader, so it will be able to load classes from secondary dexes. Fortunately, there's a library that does that for you. Add it to your app's dependencies:

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

You need to call the ClassLoader patch code as soon as possible. MultiDexApplication class's documentation suggests three ways to do that (pick one of them, one that's most convenient for you):

1 - Declare MultiDexApplication class as the application in your AndroidManifest.xml:

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

2 - Have your Application class extend MultiDexApplication class:

public class MyApplication extends MultiDexApplication { .. }

3 - Call MultiDex#install from your Application#attachBaseContext method:

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

Update 1 (10/17/2014):
As anticipated, multidex support is shipped in revision 21 of Android Support Library. You can find the android-support-multidex.jar in /sdk/extras/android/support/multidex/library/libs folder.


Multi-dex support solves this problem. dx 1.8 already allows generating several dex files.
Android L will support multi-dex natively, and next revision of support library is going to cover older releases back to API 4.

It was stated in this Android Developers Backstage podcast episode by Anwar Ghuloum. I've posted a transcript (and general multi-dex explanation) of the relevant part.

pRaNaY
  • 24,642
  • 24
  • 96
  • 146
Alex Lipov
  • 13,503
  • 5
  • 64
  • 87
  • 2
    blog post is a saver! :D – nadavfima Oct 19 '14 at 07:59
  • Marking this as the answer as of time of this comment. – Edison Oct 20 '14 at 16:52
  • Hi Alex, thanks for all the info. Today i tried to multidex my app according to the new Google Documentation and it compiles just fine but when running it, i get the following exception: java.lang.RuntimeException: Unable to instantiate application android.support.multidex.MultiDexApplication: java.lang.ClassNotFoundException: Didn't find class "android.support.multidex.MultiDexApplication" on path: DexPathList Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.multidex.MultiDexApplication" on path: – Roberto Betancourt Nov 04 '14 at 16:57
  • @dustedrob Have you added the support library as dependency? – Alex Lipov Nov 04 '14 at 17:03
  • I did: compile 'com.android.support:multidex:1.0.0' and compile 'com.android.support:appcompat-v7:21.0.0'. I made sure to have the latest support library 8 – Roberto Betancourt Nov 04 '14 at 18:03
  • I have installed the latest Android Support Library revision 21.0.1, using the Android SDK Manager. I then restarted the Luna Eclipse, and tried to run my Project, it is still giving me the same problem. Please help me solve my problem. – Sri Krishna Nov 05 '14 at 12:08
  • this solution for android studio or eclipse, I have same problem and using eclipse juno – Lokesh Nov 07 '14 at 06:07
  • @Lokesh Android Studio only. For eclipse, see my answer here: http://stackoverflow.com/a/26556209/1233652 – Alex Lipov Nov 07 '14 at 07:38
  • If you are using Android Studio make sure that it is at least version 0.9. – pkramaric Dec 01 '14 at 19:44
  • 39
    Anything for eclipse users? – Muhammad Babar Feb 23 '15 at 22:39
  • @AlexLipov Eversince i have added this option i keep on getting crash at NoClassDefFoundError on most of my functions everywhere in code. What has happened? i am using android studio 1.1.0 – Muhammad Umar Apr 05 '15 at 12:21
  • @MuhammadUmar See if this helps: http://stackoverflow.com/questions/26655541. If it doesn't, post your stack trace. Do you use plugin's 'multiDexEnabled = true' or adding dx parameters manually? – Alex Lipov Apr 05 '15 at 12:44
  • @AlexLipov I Used multiDexEnabled = true – Muhammad Umar Apr 05 '15 at 13:06
  • @MuhammadUmar can you post your stack trace (on external resource, i.e. http://privatepaste.com and post the link here)? – Alex Lipov Apr 05 '15 at 13:13
  • http://privatepaste.com/8e81fecf14 check this. I am getting NoClassDefFoundError at new GetAllContacts().execute();. There is no other stackTrace Info except this error. Its extremely simple code. If i comment out this, there are a lot other places where i get this same error – Muhammad Umar Apr 05 '15 at 13:53
  • @MuhammadUmar Start with verifying that your GetAllContacts class is listed in maindexlist (/app/build/intermediates/multi-dex/{debug/release}/maindexlist.txt). Also, look for verifier warnings in logcat (dalvikvm with VFY tag). – Alex Lipov Apr 05 '15 at 15:30
  • 52
    @MuhammadBabar There is Android studio for Eclipse users. – VipulKumar May 14 '15 at 07:55
  • Adding Multi-Dex has the disadvantage that build time increases significantly. My build time went up to 4 mins on enabling Multi-Dex. Its best to avoid it (eg by selectively compile Google Play service APIs into your app see https://developers.google.com/android/guides/setup). – Mohammed Ali Aug 15 '15 at 09:46
  • 2
    @MohammedAli Sure, avoid using it if you can. But what should you do if you *really* have too many methods in your app, and you already tried all the tricks like the one that you mentioned? Regarding the build time - there's solution for this, at least for development builds - see my answer here: http://stackoverflow.com/a/30799491/1233652 – Alex Lipov Aug 15 '15 at 13:22
  • thanks! the entire google build system is a piece of work. – Iman Akbari Sep 16 '15 at 09:50
  • How does this work for Maven users? How do I generate the main dex list via maven? – New Guy Sep 22 '15 at 17:22
  • hello , @Alex Lipov After multiDexEnabled = true in my gradle file , in my device samsung galaxy edge -> run sccuessfully but in other devices it generate fatal error class not found.. so any solution for it ? – Joseph Mekwan Sep 30 '15 at 05:04
  • @JosephMekwan There're many ClassNotFound/multidex related questions in SO - search for them. If you can't find something that solves your problem then post new question. – Alex Lipov Sep 30 '15 at 07:08
  • For eclipse users, after adding the jar to libs, take a look at [this](http://developer.android.com/reference/android/support/multidex/MultiDexApplication.html) Also all the jars/library projects that your project uses should only have 1 copy and shouldn't have any transitive dependency. You can confirm this by seeing all the jars in bin/dexedLibs directory of your project. There should only be 1 copy of each jar in it – Sheraz Ahmad Khilji Sep 30 '15 at 20:18
  • 2
    On Qt for Android, I was having issues at runtime for my app when integrating Facebook+Twitter's SDKs together, even after enabling multidex support (this one error in particular gave me nightmares: `java.lang.ClassNotFoundException: Didn't find class "org.qtproject.qt5.android.QtActivityDelegate" on path: DexPathList[[],nativeLibraryDirectories=[/vendor/lib, /system/lib]]`). It turned out that my mistake was that I wasn't applying the additional steps for Android support prior to 5.0. With that said, option #3 solved it, and I had no more `ClassNotFoundException` issues. Thanks, @Alex Lipov! – rob Nov 13 '15 at 18:51
  • if you wish to know more info about what happend here try to read this: https://medium.com/@rotxed/dex-skys-the-limit-no-65k-methods-is-28e6cb40cf71#.cni1gvx9i – Fernando Bustos Nov 26 '15 at 23:47
  • This solved my problem thank you. But I want to know the reason why it occured and how this piece of code solved the issue. – viper Mar 28 '17 at 05:59
  • @viper Did you read the [official documentation](https://developer.android.com/studio/build/multidex.html) that I've mentioned in my answer? – Alex Lipov Mar 28 '17 at 07:30
  • Just blindly pasted the code snippets from this answer in the respective files, and it worked like a charm. – Rocky Inde Apr 29 '17 at 17:42
78

As already stated, you have too many methods (more than 65k) in your project and libaries.

Prevent the Problem: Reduce the number of methods with Play Services 6.5+ and support-v4 24.2+

Since often the Google Play Services is one of the main suspects in "wasting" methods with its 20k+ methods. Google Play Services version 6.5 or later, it is possible for you to include Google Play Services in your application using a number of smaller client libraries. For example, if you only need GCM and maps you can choose to use these dependencies only:

dependencies {
    compile 'com.google.android.gms:play-services-base:6.5.+'
    compile 'com.google.android.gms:play-services-maps:6.5.+'
}

The full list of sub libraries and its responsibilities can be found in the official google doc.

Update: Since Support Library v4 v24.2.0 it was split up into the following modules:

support-compat, support-core-utils, support-core-ui, support-media-compat and support-fragment

dependencies {
    compile 'com.android.support:support-fragment:24.2.+'
}

Do note however, if you use support-fragment, it will have dependencies to all the other modules (i.e. if you use android.support.v4.app.Fragment there is no benefit)

See here the official release notes for support-v4 lib


Enable MultiDexing

Since Lollipop (aka build tools 21+) it is very easy to handle. The approach is to work around the 65k methods per DEX file problem to create multiple DEX files for your app. Add the following to your Gradle build file (this is taken from the official google doc on applications with more than 65k methods):

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

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

The second step is to either prepare your Application class or if you don't extend Application use the MultiDexApplication in your Android Manifest:

Either add this to your Application.java

@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

or use the provided application from the mutlidex lib

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

Prevent OutOfMemory with MultiDex

As further tip, if you run into OutOfMemory exceptions during the build phase you could enlarge the heap with

android {
    ...
    dexOptions {
        javaMaxHeapSize "4g"
    }
}

which would set the heap to 4 gigabytes.

See this question for more detail on the DEX heap memory issue.


Analyze the source of the Problem

To analyze the source of the methods the Gradle plugin https://github.com/KeepSafe/dexcount-gradle-plugin can help in combination with the dependency tree provided by Gradle with e.g.

.\gradlew app:dependencies

See this answer and question for more information on method count in android

Patrick
  • 33,984
  • 10
  • 106
  • 126
  • I've used Play Services 6.5+ solution and it worked perfectly. Incredible useful tip. Thanks so much! – Hoang Nguyen Huu Apr 23 '15 at 09:24
  • I'd upvote more if I could - cutting out all the other Play Services stuff that we weren't using fixed this issue, without having to resort to multi-dex, which has negative performance implications when building. – Sean Barbeau Aug 07 '15 at 14:24
  • 1
    Than you so much with tears in my eyes. You saved me – insomniac Aug 16 '15 at 07:48
  • I used client library for GCM, because I am using only gcm service from play service, now it fixed my problem with this. Thanks! to save my time. – Ankit Aug 25 '16 at 10:51
57

Your project is too large. You have too many methods. There can only be 65536 methods per application. see here https://code.google.com/p/android/issues/detail?id=7147#c6

Michał Klimczak
  • 12,674
  • 8
  • 66
  • 99
blobbie
  • 1,279
  • 1
  • 10
  • 8
  • I see. I do have lots of dependencies for this project. It builds fine before I moved to use maven though, maybe maven added unnecessary dependencies. Will double check. – Edison Mar 11 '13 at 15:29
  • 5
    To be more specific, there can only be 65,536 methods per Dalvik executable (dex) file. And an application (APK) can have more than one dex file with such things as custom loading. – Dennis Sheil May 30 '13 at 06:46
  • 7
    It's really embarrassing bug for android! Anyway, In me case I removed Jar that was in the libs and wasn't in use, and the app compiled – David Jun 08 '14 at 12:42
  • Time to clean up my project :/ – Decoy Jun 24 '14 at 13:07
  • 1
    A quick fix would be to use Proguard also with the debug builds – aleb Jul 08 '14 at 10:29
12

The below code helps, if you use Gradle. Allows you to easily remove unneeded Google services (presuming you're using them) to get back below the 65k threshold. All credit to this post: https://gist.github.com/dmarcato/d7c91b94214acd936e42

Edit 2014-10-22: There's been a lot of interesting discussion on the gist referenced above. TLDR? look at this one: https://gist.github.com/Takhion/10a37046b9e6d259bb31

Paste this code at the bottom of your build.gradle file and adjust the list of google services you do not need:

def toCamelCase(String string) {
    String result = ""
    string.findAll("[^\\W]+") { String word ->
        result += word.capitalize()
    }
    return result
}

afterEvaluate { project ->
    Configuration runtimeConfiguration = project.configurations.getByName('compile')
    ResolutionResult resolution = runtimeConfiguration.incoming.resolutionResult
    // Forces resolve of configuration
    ModuleVersionIdentifier module = resolution.getAllComponents().find { it.moduleVersion.name.equals("play-services") }.moduleVersion

    String prepareTaskName = "prepare${toCamelCase("${module.group} ${module.name} ${module.version}")}Library"
    File playServiceRootFolder = project.tasks.find { it.name.equals(prepareTaskName) }.explodedDir

    Task stripPlayServices = project.tasks.create(name: 'stripPlayServices', group: "Strip") {
        inputs.files new File(playServiceRootFolder, "classes.jar")
        outputs.dir playServiceRootFolder
        description 'Strip useless packages from Google Play Services library to avoid reaching dex limit'

        doLast {
            copy {
                from(file(new File(playServiceRootFolder, "classes.jar")))
                into(file(playServiceRootFolder))
                rename { fileName ->
                    fileName = "classes_orig.jar"
                }
            }
            tasks.create(name: "stripPlayServices" + module.version, type: Jar) {
                destinationDir = playServiceRootFolder
                archiveName = "classes.jar"
                from(zipTree(new File(playServiceRootFolder, "classes_orig.jar"))) {
                    exclude "com/google/ads/**"
                    exclude "com/google/android/gms/analytics/**"
                    exclude "com/google/android/gms/games/**"
                    exclude "com/google/android/gms/plus/**"
                    exclude "com/google/android/gms/drive/**"
                    exclude "com/google/android/gms/ads/**"
                }
            }.execute()
            delete file(new File(playServiceRootFolder, "classes_orig.jar"))
        }
    }

    project.tasks.findAll { it.name.startsWith('prepare') && it.name.endsWith('Dependencies') }.each { Task task ->
        task.dependsOn stripPlayServices
    }
}
JohnnyLambada
  • 12,700
  • 11
  • 57
  • 61
mcm
  • 655
  • 9
  • 10
  • Love it! def needed as companies like Google keep inflating the packages. – Edison Sep 26 '14 at 17:57
  • 1
    Nice - this did the job spot on. No hasswle and no worry! – slott Sep 29 '14 at 10:59
  • Note: this deleted google play services jars in my Android SDK in Android Studio! A bad idea since it's not easy to revert back to original jars. The author should modify the script to change the jars in the build directory. – inder Oct 02 '14 at 00:08
  • @inder: I didn't have that problem. However, I did have to do a `clean` each time I monkeyed with the excludes (we use analytics). – JohnnyLambada Oct 22 '14 at 17:40
  • how to exclude this from release builds? – user1324936 Nov 09 '14 at 20:25
  • I didn't work for me, I got `Error:Gradle: Execution failed for task ':myapp:compileDevDebugJava'. > Compilation failed; see the compiler error output for details. /Users/eric/tmp/myapp/android/MyApp/myapp/src/main/java/com/myapp/data/core/ChannelAnalyticDataHelper.java Error:(14, 36) Gradle: package com.google.android.gms.games does not exist` – ericn Jan 05 '15 at 07:10
6

I've shared a sample project which solve this problem using custom_rules.xml build script and a few lines of code.

I used it on my own project and it is runs flawless on 1M+ devices (from android-8 to the latest android-19). Hope it helps.

https://github.com/mmin18/Dex65536

mmin
  • 221
  • 2
  • 4
  • 1
    Thanks for the scripts. you should watch out for ART. Device may convert only your default dex and not the secondary ones. Proguard solutions should be preferred. – Edison Mar 31 '14 at 17:35
  • 2
    When i import the projects into the Eclipse and run it gives error. "Unable to execute dex: method ID not in [0, 0xffff]: 65536". Can you explaing the usage of the project – Karacago Jul 03 '14 at 12:36
6

Faced the same problem and solved it by editing my build.gradle file on the dependencies section, removing:

compile 'com.google.android.gms:play-services:7.8.0'

And replacing it with:

compile 'com.google.android.gms:play-services-location:7.8.0'
compile 'com.google.android.gms:play-services-analytics:7.8.0' 
5

Try adding below code in build.gradle, it worked for me -

compileSdkVersion 23
buildToolsVersion '23.0.1'
defaultConfig {
    multiDexEnabled true
}
Sunita
  • 1,219
  • 12
  • 16
2

The perfect solution for this would be to work with Proguard. as aleb mentioned in the comment. It will decrease the size of the dex file by half.

shimi_tap
  • 7,822
  • 5
  • 23
  • 23
  • 1
    Agreed, with an increasingly large google play services jar especially *(18k methods by itself) – Edison Jul 31 '14 at 16:22
2

You can analyse problem (dex file references) using Android Studio:

Build -> Analyse APK ..

On the result panel click on classes.dex file

And you'll see:

enter image description here

alexshr
  • 989
  • 8
  • 12
0

gradle + proguard solution:

afterEvaluate {
  tasks.each {
    if (it.name.startsWith('proguard')) {
        it.getInJarFilters().each { filter ->
            if (filter && filter['filter']) {
                filter['filter'] = filter['filter'] +
                        ',!.readme' +
                        ',!META-INF/LICENSE' +
                        ',!META-INF/LICENSE.txt' +
                        ',!META-INF/NOTICE' +
                        ',!META-INF/NOTICE.txt' +
                        ',!com/google/android/gms/ads/**' +
                        ',!com/google/android/gms/cast/**' +
                        ',!com/google/android/gms/games/**' +
                        ',!com/google/android/gms/drive/**' +
                        ',!com/google/android/gms/wallet/**' +
                        ',!com/google/android/gms/wearable/**' +
                        ',!com/google/android/gms/plus/**' +
                        ',!com/google/android/gms/topmanager/**'
            }
        }
    }
  }
}
Oleg Khalidov
  • 5,108
  • 1
  • 28
  • 29
0

Remove some jar file from Libs folder and copy to some other folder, And Go to _Project Properties > Select Java Build Path, Select Libraries, Select Add External Jar, Select the Removed jar to your project, Click save, this will be added under Referenced Library instead of Libs folder. Now clean and Run your project. You dont need to add Any code for MultDex. Its simply worked for me.

Lakshmanan
  • 1,671
  • 2
  • 26
  • 42
0

I was facing the same issue today what worked for is below down

For ANDROID STUDIO... Enable Instant Run

In File->Preferences->Build, Execution, Deployment->Instant Run-> Check Enable Instant run for hot swap...

Hope it helps

Abdul Waheed
  • 4,540
  • 6
  • 35
  • 58