alwaystest / Blog

24 stars 2 forks source link

64K的Dex #38

Open alwaystest opened 7 years ago

alwaystest commented 7 years ago

64K的Dex

标签(空格分隔): Android


开发需要兼容低于Android-21(5.0)系统的软件的时候,大家都知道生成APK包的时候可能出现65536方法数的问题。

只要按照Google官方的解决方案开启MuntiDex解决。

我记得之前看过的文章说Android Studio在某个版本以后可以直接按照下面的方法开启multiDex,只要这么一步就足够了。怎么最近查到的文章包括Google官方给的说明都还需要多加一个依赖项目,还得配置Application。难道是我记错了?

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

今天又遇到一个新的问题,编译时提示Cannot merge new index xxx into a non-jumbo instruction

原来不止方法数有64K限制,别的地方也有这个限制。根据这里的说法

typeIds、protoIds 以及 fieldIds也是如此。

不过这个解决起来倒是简单,开启jumboMode就可以了。巨大模式 -_-!

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...
    }
    dexOptions {
        jumboMode true
    }
}

这种情况开启multiDex模式也可以解决,但是太麻烦了,而且multiDex会减慢启动速度。

看来Shrink Your Code and Resources势在必行了。

Android厂商跟进系统的速度太慢了,4.X的用户不能抛弃。等主流用户都用上了5.X,或者直接蹦6.X。就可以省好多事了。


2017.03.17 Update

Google官方放话为了支持Java8的特性,将来不考虑升级Jack工具链了。所以不是所有的新技术都值得第一时间去尝鲜啊。

2016.11.18 Update

今天突然想起来仔细看看Android N 都更新了点啥。

然后发现JACK编译器也能避免64K的问题。

Jack ( Java Android Compiler Kit )全新的编译工具集

Jack 最大最大的优点,你不用再操心 65K 方法限制的问题了! Jack 在 Compile 的时候就已经解决了!『65k 方法限制』将成为过去式中存在的名词了。 @代码家

然后看看JACK这个新的编译器。(虽然还是使用的MultiDex的老方案)

不再需要独立的 ProGuard。Jack 支持读取旧的 ProGuard 配置,完成 shrinking, obfuscation 的工作

没有 .class 文件了,直接操纵或读取 Java 字节码的各种工具如 JaCoCo/Lint/Mokito/Retrolambda 没有了用武之地。(引用注: 这里应该是Mockito吧)

Jack 当前的局限(截止到2016/03/15) 暂时还不支持 Android Studio 2.0 的 Instant Run 特性 暂时还不支持 data binding @淘宝前端团队

2016.11.18再次查看官方网站,看到

Note that beginning in Android 7.0 (N), Jack supports code coverage with JaCoCo.

于是我就懵了,虽然JACK支持了MultiDex,内建了代码压缩和混淆。但是Mockito不能使用,我怎么跑单元测试啊。但是上面又说了Android N开始,JACK支持JaCoCo。代码覆盖率这个概念,应该是支持单元测试的呀。究竟怎么使用JACK,同时还要保证之前的持续集成系统能够正常工作,有待踩坑。

对于导致64K问题的详细分析我觉得上面引用过的这篇文章讲的并不是很清楚,起码我看完之后还是理解错了。以为是Dex文件结构定义造成的问题。看过淘宝前端团队杰风居的分析,才搞明白

65k 问题是因为 dalvik bytecode 中的指令格式使用了 16 位来放 @CCCC 导致的;所以,不仅 Method 数目不能超过 65k, Field 和 Class 数目也不能超过 65k。

注:我个人更喜欢使用64K来描述这个问题。本来嘛,64 * 1024 == 65536,学硬盘厂商用65 * 1000我是不赞成的。虽然Android官方说这个问题也是使用65K来描述。