respect for the original:http://blog.csdn.net/yuanzeyao/article/details/41809423
As an Android developer, I believe you should have heard about the limit of Android methods to 65K, and as the application function continues to enrich, someday you will encounter an exception:
Conversion to Dalvik format failed:unable toexecute dex:method ID not in [0, 0xFFFF]: 65536
Some students may say that to solve this problem is very simple, we only need to configure a sentence in the Project.proterty OK,
Dex.force.jumbo=true
Yes, by adding this phrase, you can actually make your app compile, but it's easy to appear on some 2.3-system machines
Install_failed_dexopt exception
For the above two exceptions, let's start by analyzing the reasons:
1, the Android system, a Dex file stored method ID with the short type of data, so that your Dex in the method can not exceed 65k
2, before the 2.3 system, the virtual machine memory is allocated only 5M
Know the reason, we have to solve the above problem, first of all, for the 65k problem, we can not change the structure of the Android system in the application layer, so we can not change the data type from short to int or other type, In other words, the number of methods in a Dex cannot exceed 65k, and we can only reduce the number of methods in one Dex, and the easiest scenario is to get rid of some useless jar packages and set some properties to public so that the Get/set method is removed. This method can only temporarily solve the problem, with the passage of time, one day there will be more than 65k of methods, after all, an application is generally in addition function, will not reduce functionality.
Let me introduce you to the two main solutions, one is to represent, some functions into plug-ins, dynamic loading, the other is a Facebook-represented subcontracting scheme, the Dex file in an APK is divided into multiple Dex files, and then dynamically load the Dex file. In fact, the core idea of the two programs is the same, the plug-in is the future to develop new features into the APK and Dex dynamic loading, and the subcontracting is to have completed the function of multiple Dex file load dynamically, in fact, I personally feel that the plug-in Scheme score package solution to better solve the problem of 65k, Because the plug-in solution can not only solve the 65k problem, but also let our application volume reduce, and sub-package can only solve the problem of 65k.
On the plug-in development, made dynamic loading, I wrote in an earlier article on its basic ideas, interested students can see
"Implementing Android Dynamic loading APK (Fragment or activity implementation)"
http://blog.csdn.net/yuanzeyao/article/details/38565345
Below we highlight the subcontracting mechanism
We know that an APK file has a Dex file inside, the Dex file is an optimized class file, so-called subcontracting, is to say a Dex file into multiple Dex files, here we agreed that the first Dex called Main.dex, The second is called Second.dex, usually at the time of subcontracting, we need to put the application to use the launch of the class into the Main.dex, not immediately need to use the class into the Second.dex, for the Android system, he will only load the default Main.dex, Second.dex to For him it might just be a resource file, it's not going to load second.dex, so I'm going to need to create a class loader for Second.dex during the app launch, so that I can load the class in Second.dex when I'm using the class.
about how to load Second.dex also have a lot of practices, with more than a few of the main
1, the simplest way is to use Dexclassloader to load, and the Dexclassloader's parent loader is set to Pathclassloader
2. Use Dexclassloader to load, and set Dexclassloader's parent loader to Pathclassloader's parent loader, set Pahtclassloader's parent loader to Dexclassloader, Take a closer look at the difference between 1 and 2
3. Put the Second.dex path into the Pathclassloader load path
For the 2nd program, in one case it is not available, For example, when Second.dex is loaded by Dexclassloader, but a class is used in the Second.dex, this class is in Main.dex, this time throws the class cannot find the exception, so this scheme can only have second.dex not use Main.dex class when
These are all theories, let's do the actual combat.
I'll show you two scenarios, one that builds Android projects based on Gradle, and one that builds Android projects based on Ant
Scenario One: Build Android projects based on Gradle and implement subcontracting
Environmental requirements: AndroidStudio0.9 above, Gradle plug-in 0.14.2 or more
1. If your project is in Eclipse, then you need to import the project into Android, you need to upgrade adt22 above
2. Open your project's Build.gradle file and check if the Gradle plugin is 0.14.2 after the Gradle plug-in is supported by the 0.14.2 after the sub-package
3, open the project under a Moudle build.gradle file, add a dependency on the Android-support-multidex.jar
4. Remove duplicate classes from third-party jar packages
5. Set the virtual machine heap memory space size to avoid oom during compilation
6, Gradle construction project, it seems that the default is not to join the so library project, so in order to avoid this situation, we need to develop so library directory, for the project from Eclipse, also need to develop SRC and resource file path
7. If your project relies on other libraries, add multidexenabled = True and Jnilibs.srcdirs =[' Libs '] two configurations in each library project respectively
8, if your project does not have custom application, then you can use Multidexapplication in Androidmanifest.xml, if your project has custom application, And is the inheritance is application, then only need to inherit multidexapplication can, if your project inherits the other application, then you need to rewrite
Attachbasecontext
@Overrideprotected void Attachbasecontext (Context base) { super.attachbasecontext (base); Multidex.install (this);}
With the above configuration, your project should have been successfully subcontracting. If the subcontracting succeeds, then you unzip your apk file and will find that there are two Dex files, through the above configuration process, We find that we have no control over which classes are in Main.dex, and which classes are in Second.dex, which are compatible with api4-api20 by configuring subcontracting in this scenario. It loads Second.dex using 3 of the above scenario
Let's take a look at the Ant-based build Android project, and implement the subcontracting process
In the above scenario, since we can't see the script for the Gradle build project, we can't control which classes are in the first Dex, which classes are in the second Dex, and in this scenario we're using ant build, ant is allowing users to define their own build scenarios, such as we can customize the build scenario, Put some third-party jar packages in the project into Second.dex, see the Open Source project for information on how this is implemented
Https://github.com/mmin18/Dex65536.git
Since the project is loaded with the scenario 2 above, for example, some third-party jar packages in Second.dex depend on some classes in the Main.dex, this scenario will be implemented, so I'm going to take this scenario out of the way, and replace the Second.dex with scenario 3, which is to set the path of the Second.dex to path ClassLoader in the Load path
I only give the solution in Android 4.4, the other systems are similar
Load Second.dex method
/** @param loader Pathclassloader @additionalClassPathEntries The Dex file to be loaded, here's our Second.dex @optimizedDirectory that's Dex. Files extracted directory */private static void Install (ClassLoader loader, list<file> additionalclasspathentries, file Optimizeddirectory) throws IllegalArgumentException, Illegalaccessexception, Nosuchfieldexception, InvocationTargetException, nosuchmethodexception {/* The patched class loader is ExPEC Ted to be a descendant of * Dalvik.system.BaseDexClassLoader. We Modify its * dalvik.system.DexPathList pathList field to append additional DEX * file entries. ////////To find the value of PathList by reflection Field Pathlistfield = FindField (loader, "pathList"); Object dexpathlist = pathlistfield.get (loader); arraylist<ioexception> suppressedexceptions = new arraylist<ioexception> ();//Will Second.dex Add to Pathclassloader's load path ExpandfieldArray (Dexpathlist, "dexelements", Makedexelements (Dexpathlist, New arraylist<file> (Additionalclas spathentries), optimizeddirectory, suppressedexceptions); if (suppressedexceptions.size () > 0) {for (IOException e:suppressedexceptions) {L OG.W (TAG, "Exception in Makedexelement", e); } Field Suppressedexceptionsfield = FindField (loader, "Dexelementssuppressedexceptio NS "); Ioexception[] Dexelementssuppressedexceptions = (ioexception[]) Suppressedexceptionsfield.get (loade R); if (dexelementssuppressedexceptions = = null) {dexelementssuppressedexceptions = Suppressedexceptions.toarray (New Ioexception[suppressedexceptions.size ()]); } else {ioexception[] combined = New Ioexception[suppressedexceptions.size () + Dexelementssuppressede Xceptions.length]; Suppressedexceptions.toarray (combined); System.arraycopy (dexelementssuppressedexceptions, 0, combined, suppressedexceptions.size (), Dex Elementssuppressedexceptions.length); Dexelementssuppressedexceptions = combined; } suppressedexceptionsfield.set (loader, dexelementssuppressedexceptions); } }
After the successful sub-package, unzip the apk file into the Assert folder, we see the following structure, LIBS.APK is the third party jar compiled after the Dex file
As for the method used in some of the methods, can be found in the Android-support-multidex.jar, here is not all posted out, if there is no clear, welcome message to discuss ...
=============================================================================================================== ==================
I just did an operation that magically solved this problem in eclipse:
Project Right click-->build path-->configure Build path-->order and export the original selected Android Private library to uncheck ....
It is estimated that this will not solve the problem completely, whether you want to solve it completely or use subcontracting.
Android unable toexecute Dex:method ID not in [0, 0xFFFF]: 65536 issues