导致 DexIndexOverflowException 的方法引用列表

list of method references which are causing DexIndexOverflowException

我遇到了导致 com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536 的问题。

我知道 multiDexEnabled 的用法,但我不想实施或使用它,因为它有一些限制。

其中之一是:

Applications that use multidex may not start on devices that run versions of the platform earlier than Android 4.0 (API level 14) due to a Dalvik linearAlloc bug (Issue 22586). If you are targeting API levels earlier than 14, make sure to perform testing with these versions of the platform as your application can have issues at startup or when particular groups of classes are loaded. Code shrinking can reduce or possibly eliminate these potential issues.

被 Google 引用 link

我想知道一种方法可以向我显示导致此问题的方法引用列表。 这样我就可以在导入我拥有的库时删除这些模块已经在我的项目中。

示例:

compile('org.apache.httpcomponents:httpmime:4.3.6') {
        exclude module: 'httpclient'
    }
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'

我建议暂时使用 multi-dex,然后使用 baksmali 对生成的 dex 文件进行带注释的十六进制转储。带注释的十六进制转储将包括方法参考列表。

baksmali -N -D out.dump -e classes.dex myapp.apk
baksmali -N -D out2.dump -e classes2.dex myapp.apk

您需要在 2 个转储文件中查找 "method_id_item section"。本节包含 dex 文件中使用的方法引用的完整列表。它看起来像

                           |-----------------------------
                           |method_id_item section
                           |-----------------------------
                           |
                           |[0] method_id_item
003c38: 0500               |  class_idx = type_id_item[5]: Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;
003c3a: b000               |  proto_idx = proto_id_item[176]: (I)V
003c3c: 1900 0000          |  name_idx = string_id_item[25]: <init>
                           |[1] method_id_item
003c40: 0500               |  class_idx = type_id_item[5]: Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;
003c42: d500               |  proto_idx = proto_id_item[213]: (Landroid/graphics/Canvas;)V
003c44: df02 0000          |  name_idx = string_id_item[735]: draw
                           |[2] method_id_item
003c48: 0500               |  class_idx = type_id_item[5]: Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;
003c4a: a400               |  proto_idx = proto_id_item[164]: ()V
003c4c: 4103 0000          |  name_idx = string_id_item[833]: generatePatternBitmap
                           |[3] method_id_item
003c50: 0500               |  class_idx = type_id_item[5]: Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;
003c52: 4500               |  proto_idx = proto_id_item[69]: ()Landroid/graphics/Rect;
003c54: 4e03 0000          |  name_idx = string_id_item[846]: getBounds
                           |[4] method_id_item
003c58: 0500               |  class_idx = type_id_item[5]: Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;
003c5a: 0c00               |  proto_idx = proto_id_item[12]: ()I
003c5c: 8403 0000          |  name_idx = string_id_item[900]: getOpacity
...

另一种方法是使用 dexlib2 编写一个小工具来读取 dex 文件并打印出方法引用。

public class DumpMethods {
    public static void main(String[] args) throws IOException {
        DexBackedDexFile dexFile = DexFileFactory.loadDexFile(args[0], 15);

        for (int i=0; i<dexFile.getMethodCount(); i++) {
            System.out.println(ReferenceUtil.getMethodDescriptor(new DexBackedMethodReference(dexFile, i)));
        }
    }
}

这将在一个简单列表中打印出方法引用:

Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;-><init>(I)V
Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;->draw(Landroid/graphics/Canvas;)V
Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;->generatePatternBitmap()V
Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;->getBounds()Landroid/graphics/Rect;
Lafzkl/development/mColorPicker/drawables/AlphaPatternDrawable;->getOpacity()I
...