Android為什么會有65536的方法數(shù)量限制

這里給大家推薦一個Android源碼網(wǎng)站:http://androidxref.com/(無需翻墻)

前言

65536是什么樣的數(shù)楞黄?2的16次方或者說64KB

下邊這個error是不是很熟悉

較高版本的Android構(gòu)建系統(tǒng)下的提示(Android 7.0及以下):

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

較高版本的Android構(gòu)建系統(tǒng)的報錯信息(Android 8.0)

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

注意:構(gòu)建時期發(fā)生的錯誤哦

為什么會出現(xiàn)64K的限制呢侦铜?

一般排查問題我們需要從問題本身入手,那么log是最重要的信息浇冰。

在構(gòu)建流程中出現(xiàn)這種問題殊霞,根據(jù)提示我們大概明白方法數(shù)過大畸悬,而這些方法是存在于編譯后的.class文件中的,而.class最后要存在于dex文件中灾部。

那么如此分析的話康铭,問題應(yīng)該存在于dex的打包流程當中,這個需要以后深入了解一下赌髓。

根據(jù)前人的一些分析从藤,我們來看看MemberIdsSection文件。代碼不多春弥,如下:

1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
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 at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * 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 and
14 * limitations under the License.
15 */
16
17package com.android.dx.dex.file;
18
19import com.android.dex.DexFormat;
20import com.android.dex.DexIndexOverflowException;
21
22import java.util.Formatter;
23import java.util.Map;
24import java.util.TreeMap;
25import java.util.concurrent.atomic.AtomicInteger;
26
27/**
28 * Member (field or method) refs list section of a {@code .dex} file.
29 */
30public abstract class MemberIdsSection extends UniformItemSection {
31
32    /**
33     * Constructs an instance. The file offset is initially unknown.
34     *
35     * @param name {@code null-ok;} the name of this instance, for annotation
36     * purposes
37     * @param file {@code non-null;} file that this instance is part of
38     */
39    public MemberIdsSection(String name, DexFile file) {
40        super(name, file, 4);
41    }
42
43    /** {@inheritDoc} */
44    @Override
45    protected void orderItems() {
46        int idx = 0;
47
48        if (items().size() > DexFormat.MAX_MEMBER_IDX + 1) {
49            throw new DexIndexOverflowException(getTooManyMembersMessage());
50        }
51
52        for (Object i : items()) {
53            ((MemberIdItem) i).setIndex(idx);
54            idx++;
55        }
56    }
57
58    private String getTooManyMembersMessage() {
59        Map<String, AtomicInteger> membersByPackage = new TreeMap<String, AtomicInteger>();
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        }
69
70        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<String, AtomicInteger> 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    }
86
87}

在48行到49中呛哟,我們看到如下可能拋出異常的情況

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

getTooManyMembersMessage()函數(shù)內(nèi)(72行到77行)有如下異常信息字符串構(gòu)造

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;

根據(jù)注釋,我們來到Dalvik 字節(jié)碼匿沛,根據(jù)表格中的解釋如下圖:

Dalvik

可以看到類型索引(16 位),由此可以知道榛鼎,無論是方法數(shù)還是字段數(shù)都不能超過65536逃呼,這也就是為什么在構(gòu)建流程中出現(xiàn)65536的報錯信息。

由此可以得出結(jié)論:

單個dex的方法或者字段數(shù)量不能超過65536

如何避免64K問題者娱?涉及到dex分包的知識抡笼,同時也是涉及到APK瘦身優(yōu)化等問題。

很多問題都需要我們?nèi)ブ泵婊器ⅲ徊讲饺ソ鉀Q推姻。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市框沟,隨后出現(xiàn)的幾起案子藏古,更是在濱河造成了極大的恐慌,老刑警劉巖忍燥,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拧晕,死亡現(xiàn)場離奇詭異,居然都是意外死亡梅垄,警方通過查閱死者的電腦和手機厂捞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來队丝,“玉大人靡馁,你說我怎么就攤上這事』茫” “怎么了臭墨?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吞加。 經(jīng)常有香客問我裙犹,道長尽狠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任叶圃,我火速辦了婚禮袄膏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掺冠。我一直安慰自己沉馆,他們只是感情好,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布德崭。 她就那樣靜靜地躺著斥黑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眉厨。 梳的紋絲不亂的頭發(fā)上锌奴,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音憾股,去河邊找鬼鹿蜀。 笑死,一個胖子當著我的面吹牛服球,可吹牛的內(nèi)容都是我干的茴恰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼斩熊,長吁一口氣:“原來是場噩夢啊……” “哼往枣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起粉渠,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤分冈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后渣叛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丈秩,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年淳衙,在試婚紗的時候發(fā)現(xiàn)自己被綠了蘑秽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡箫攀,死狀恐怖肠牲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情靴跛,我是刑警寧澤缀雳,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站梢睛,受9級特大地震影響肥印,放射性物質(zhì)發(fā)生泄漏识椰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一深碱、第九天 我趴在偏房一處隱蔽的房頂上張望腹鹉。 院中可真熱鬧,春花似錦敷硅、人聲如沸功咒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽力奋。三九已至,卻和暖如春幽七,著一層夾襖步出監(jiān)牢的瞬間景殷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工锉走, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留滨彻,地道東北人藕届。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓挪蹭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親休偶。 傳聞我的和親對象是個殘疾皇子梁厉,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容