这里给大家推荐一个Android源码网站:http://androidxref.com/(无需)

前言

65536是什么样的数?2的16次方或者说64KB

下边这个error是不是很熟悉

较高版本的Android构建系统下的提示(Android 7.0及以下):

Conversion to Dalvik format failed:Unable to execute dex: method ID not in [0, 0xffff]: 65536

较高版本的Android构建系统的报错信息(Android 8.0)

trouble writing output:Too many field references: 131000; max is 65536.You may try using --multi-dex option.

注意:构建时期发生的错误哦

为什么会出现64K的限制呢?

一般排查问题我们需要从问题本身入手,那么log是最重要的信息。

在构建流程中出现这种问题,根据提示我们大概明白方法数过大,而这些方法是存在于编译后的.class文件中的,而.class最后要存在于dex文件中。

那么如此分析的话,问题应该存在于dex的打包流程当中,这个需要以后深入了解一下。

根据前人的一些分析,我们来看看MemberIdsSection文件。代码不多,如下:

1 /*2 * Copyright (C) 2007 The Android Open Source Project3 *4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 *8 *      http://www.apache.org/licenses/LICENSE-2.09 *10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */1617package com.android.dx.dex.file;1819import com.android.dex.DexFormat;20import com.android.dex.DexIndexOverflowException;2122import java.util.Formatter;23import java.util.Map;24import java.util.TreeMap;25import java.util.concurrent.atomic.AtomicInteger;2627/**28 * Member (field or method) refs list section of a {@code .dex} file.29 */30public abstract class MemberIdsSection extends UniformItemSection {3132    /**33     * Constructs an instance. The file offset is initially unknown.34     *35     * @param name {@code null-ok;} the name of this instance, for annotation36     * purposes37     * @param file {@code non-null;} file that this instance is part of38     */39    public MemberIdsSection(String name, DexFile file) {40        super(name, file, 4);41    }4243    /** {@inheritDoc} */44    @Override45    protected void orderItems() {46        int idx = 0;4748        if (items().size() > DexFormat.MAX_MEMBER_IDX + 1) {49            throw new DexIndexOverflowException(getTooManyMembersMessage());50        }5152        for (Object i : items()) {53            ((MemberIdItem) i).setIndex(idx);54            idx++;55        }56    }5758    private String getTooManyMembersMessage() {59        Map membersByPackage = new TreeMap();60        for (Object member : items()) {61            String packageName = ((MemberIdItem) member).getDefiningClass().getPackageName();62            AtomicInteger count = membersByPackage.get(packageName);63            if (count == null) {64                count = new AtomicInteger();65                membersByPackage.put(packageName, count);66            }67            count.incrementAndGet();68        }6970        Formatter formatter = new Formatter();71        try {72            String memberType = this instanceof MethodIdsSection ? "method" : "field";73            formatter.format("Too many %1$s references to fit in one dex file: %2$d; max is %3$d.%n" +74                            "You may try using multi-dex. If multi-dex is enabled then the list of " +75                            "classes for the main dex list is too large.%n" +76                    "References by package:",77                    memberType, items().size(), DexFormat.MAX_MEMBER_IDX + 1);78            for (Map.Entry entry : membersByPackage.entrySet()) {79                formatter.format("%n%6d %s", entry.getValue().get(), entry.getKey());80            }81            return formatter.toString();82        } finally {83            formatter.close();84        }85    }8687}

在48行到49中,我们看到如下可能抛出异常的情况

if (items().size() > DexFormat.MAX_MEMBER_IDX + 1) {     throw new DexIndexOverflowException(getTooManyMembersMessage());}

getTooManyMembersMessage()函数内(72行到77行)有如下异常信息字符串构造

String memberType = this instanceof MethodIdsSection ? "method" : "field";           formatter.format("Too many %1$s references to fit in one dex file: %2$d; max is %3$d.%n" +                            "You may try using multi-dex. If multi-dex is enabled then the list of " +                            "classes for the main dex list is too large.%n" +                    "References by package:",                    memberType, items().size(), DexFormat.MAX_MEMBER_IDX + 1);

同时我们还要注意DexFormat类,

    /**     * Maximum addressable field or method index.     * The largest addressable member is 0xffff, in the "instruction formats" spec as field@CCCC or     * meth@CCCC.     */   public static final int MAX_MEMBER_IDX = 0xFFFF;

根据注释,我们来到Dalvik 字节码,根据表格中的解释如下图:

Android为什么会有65536的方法数量限制_第1张图片

可以看到类型索引(16 位),由此可以知道,无论是方法数还是字段数都不能超过65536,这也就是为什么在构建流程中出现65536的报错信息。

由此可以得出结论:

单个dex的方法或者字段数量不能超过65536

如何避免64K问题?涉及到dex分包的知识,同时也是涉及到APK瘦身优化等问题。

很多问题都需要我们去直面,一步步去解决。

更多相关文章

  1. 记录关于Gradle : Build Running的解决方法
  2. Android 开机震动的调用位置以及打开关闭方法
  3. Android中计算text文字大小的几个方法
  4. Android的DialogFragment的基本使用方法

随机推荐

  1. Android dialog设置无背景
  2. android 圆角布局
  3. Android 在Camera 的 SurfaceView添加控
  4. Android AnalogClock and DigitalClock e
  5. 基于Android系统软件管理器源码
  6. Android中Handler使用实例
  7. Android SDcard 文件读写,RandomAccessFil
  8. Android 采用DOM解析XML内容 【学习记录
  9. Android 来电状态监听
  10. Android查看手机线程指令