Auto-instrumentation properties for multidex apps

There is a limit to the number of referenced methods in a given .dex file. The specification limit for this number is 65,536. Android refers to this limit as the 64K reference limit.

Android introduced the ART runtime with Android 5.0, which natively supports multi-dex applications. 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 upon app startup must be part of the primary .dex file (classes.dex).

Because auto-instrumentation inserts the Mobile OneAgent start-up routine into the application start procedure, the Mobile OneAgent code must be part of the primary .dex file. Auto-instrumentation moves some classes from the primary .dex file into another .dex file if there isn't 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.

Note:
Auto-instrumentation analyzes class dependencies based on the byte code of the application start procedure. If you hide your dependencies, for example with reflection, auto-instrumentation can't detect all your application start dependencies. If you use the properties multiDexKeepFile and/or multiDexKeepProguard from the Android Gradle plugin, you must inform the auto-instrumentation script about the specified classes. In this case, it's recommended using the auto-instrumentation property DTXMultiDexKeepFile, as shown 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

The following properties fine-tune auto-instrumentation for mutlidex applications.

  • Use the DTXPrimaryDexLimit and DTXSecondaryDexLimit properties to configure the limit of referenced methods for the primary and the secondary .dex files.
  • Use the DTXMultiDexKeep and DTXMultiDexKeepFile properties to configure the internal main dex list from auto-instrumentation.

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. Auto-instrumentation also adds the Mobile OneAgent code into the primary .dex file. For every .dex file, the number of referenced methods is analyzed and adapted before the instrumentation step. Auto-instrumentation 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, auto-instrumentation 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 the value is nearly 64K. This configuration should fit most applications and keep changes to a minimum. If auto-instrumentation fails for your application, you must update these two properties.

For the primary .dex file, auto-instrumentation generates an internal main dex list and doesn't move the classes to another .dex file. If you use the Android Gradle plugin to build you APK file, it's recommended that you use the DTXMultiDexKeepFile property to synchronize the internal main dex list from the Dynatrace Gradle plugin with the Android Gradle plugin. The Android Gradle plugin generates a maindexlist.txt file for every build variant and updates this file automatically, when you rebuild your application. 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 your 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 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. Auto-instrumentation detects the dependencies of the specified class..