Using multiple .dex files for Android instrumentation
This is documentation for the legacy version 7.x. For the most recent version see Android Agent v8.x.
Version 8.x is only supported with AppMon 2018 October!
When using multiple .dex
for Android auto-instrumentation, there is a limit on the number of referenced methods in a given .dex
file. The specification limit for this number is 65,536. Android refers to that limit as the 64K reference limit.
Android introduced the ART runtime with Android 5.0, which natively supports multi-dex applications. But for platforms prior to Android 5.0, Android uses the Davlik runtime, which only supports single-dex applications. The multidex support library lets you use additional .dex
files after the MultiDex.install()
task completes. Therefore all classes loaded at the app start must be part of the primary .dex
file (classes.dex
).
Because the auto-instrumentor inserts the agent start-up routine into the application start procedure, the agent code has to be part of the primary .dex
file. The auto-instrumentor moves some classes from the primary .dex
file into another .dex
file if there is not enough space in the primary .dex
file. For most applications, the default settings should work, but for some apps you must fine-tune the settings.
The auto-instrumentor analyzes class dependencies based on the byte code of for application start procedure. If you hide your dependencies, for example with reflection, the auto-instrumentor can't detect all your application start dependencies. If you use the Android Gradle multiDexKeepFile
and/or multiDexKeepProguard
properties, adding the specified classes also to the corresponding auto-instrumentor properties is recommended, or use the DTXMultiDexKeepFile
property as descripted in the next section.
You should test the application start on a device with Android 4.4 or lower. If the application crashes with a java.lang.NoClassDefFoundError
, then you have to add the missing class to the corresponding auto-instrumentation properties.
Fine-tune the multidex preparation step
Following properties fine-tune auto-instrumentation for mutlidex applications.
- Use the
DTXPrimaryDexLimit
andDTXSecondaryDexLimit
properties to configure the limit of referenced methods for the primary and the secondary.dex
files. - Use the
DTXMultiDexKeep
andDTXMultiDexKeepFile
properties to configure the auto-instrumentor internal main dex list.
The instrumentation step increases the number of referenced methods (depending on your implementation) and fails if the number of referenced methods exceeds the 64K limit. The auto-instrumentor also adds the agent code into the primary .dex
file. For every .dex
file, the number of referenced methods is analyzed and adapted before the instrumentation step. The auto-instrumentator adapts the number of referenced methods by moving a precalculated number of classes from the .dex
file to another .dex
file. Use the DTXPrimaryDexLimit
and DTXSecondaryDexLimit
properties to configure the final limit of referenced methods for this step. Use the DTXPrimaryDexLimit
property to set the limit for the primary .dex
file (classes.dex
) and the DTXSecondaryDexLimit
property sets the limit for the secondary .dex
files, such as classes2.dex
.
Currently, the auto-instrumentor can't calculate the number of added methods and therefore uses default values for the limits. The default value for DTXPrimaryDexLimit
is around 62K and for DTXSecondaryDexLimit
it is nearly 64K. This configuration should fit most applications and also keeps the changes to a minimum. If the auto-instrumentation fails for your application, then you have to update the two properties.
For the primary .dex
file the auto-instrumentor generates an internal main dex list and does not move the classes to another .dex
file. If using the Android Gradle plugin to build you APK file, set the DTXMultiDexKeepFile
property. The Android Gradle plugin generates a maindexlist.txt
file. This file contains a list of classes, which have to be part of the primary .dex
file. You should specify this file with the DTXMultiDexKeepFile
property. For example:
DTXMultiDexKeepFile=<path_to_project>/<project>/<module>/build/intermediates/multi-dex/<build_variant>/maindexlist.txt
You can also specify you own class list in a file, to be part of the primary .dex
file. Only one class per line is accepted. The class name must end with the .class
suffix. Separate the package parts with a slash (for example com/example/Foo.class
). You can only specify one file for the DTXMultiDexKeepFile
property. The auto-instrumentor does not analyze the specified classes' dependecies. You must track them manually.
Use the DTXMultiDexKeep
property if you don't want to track dependencies manually. The auto-instrumentor analyzes the specified classes and keeps these classes with their dependencies in the primary .dex
file. Use the DTXMultiDexKeep
to create a list of packages and classes. For example:
DTXMultiDexKeep=com.example.*, com.example2.Foo
This property is very useful when for resolving a java.lang.NoClassDefFoundError
message on application start-up for an Android 4.x device. Add the classes (mentioned in the error message) to the DTXMultiDexKeep
property. The auto-instrumentor detects the class dependencies.