Androidはなぜ65536の方法で数量制限があるのか

11342 ワード

ここではAndroidソースサイトをお勧めします.http://androidxref.com/(不要)
前言
65536はどんな数ですか.2の16回または64 KB
下の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.

注意:構築時期に発生したエラーですよ
なぜ64 Kの制限が出るのでしょうか?
一般的に問題を調べるには、問題自体から着手する必要があります.logは最も重要な情報です.
構築プロセスでこのような問題が発生すると、コンパイル後の.classファイルに存在し、.classが最後にdexファイルに存在することを示すヒントに従って、方法の数が大きすぎることがわかります.
では、このように分析すると、問題はdexのパッケージプロセスに存在するはずで、これは後で深く理解する必要があります.
先人のいくつかの分析に基づいて、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 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        }
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 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()関数内(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を超えない
64 K問題を回避するにはどうすればいいですか?dexパッケージに関する知識は、APKダイエットの最適化などの問題にも関連しています.
多くの問題は私たちが直面し、一歩一歩解決しなければならない.