前段时间中途接手了一个6.0项目,前期的基础配置工作上个同事已经做了,比如USER版本要开odex,以缩短首次开机时间。
事实上,在6.0上配置odex很简单,也都形成了共识,只需要修改几行脚本就ok了,但是同事是参考以前老项目配置的,可能是老的配置方式有些不妥,主要表现在ENG版本也开了odex,这样一来,后期修改模块之后,单编push进去可能会用不了,所以也就算挖了个坑。
为了填这个坑,关闭ENG版本的odex功能,因为只是关闭ENG版本的,所以我也就没revert他的记录,而是在他的基础上接着改的。
这个坑就算填好了,但是我忘了clean编译,而是remake了一下USER版本,看到有odex输出(实际是之前编出来的),想当然的认为改好了。结果14号出版本的时候,USER版本没编出odex,整个人都懵了,感情填了一个坑又挖出来一个新的坑,自己还是跳进去了。
为了避免以后还会跳坑,这里对odex功能做个简单整理。
开odex优化首次开机速度,是牺牲空间换取时间的做法,仅限于空间足够的设备。开了odex之后,在编译的时候,整个system image就会被预先优化。由于在启动时不再需要进行app的dex文件进行优化(dex2oat操作)从而提升其启动速度。
关于odex,有几个下面几个宏开关:
1、WITH_DEXPREOPT
这个开关在6.0 USER版本上是默认开启的,意思就是USER版本要开odex预编译。
那么问题就来了,既然 WITH_DEXPREOPT := true 默认开启,那么为什么首次启动依然耗时很长呢?这个就和第二个宏开关——DONT_DEXPREOPT_PREBUILTS有关了。
2、DONT_DEXPREOPT_PREBUILTS
如果我们不想把prebuilts目录中的第三方应用进行预先优化(这些应用在他们的Android.mk文件中有include$(BUILD_PREBUILT) ),而是希望这些app通过playstore 或者app提供商进行升级,那么我们可以打开这个宏开关。
事实上,6.0上面,这个宏开关也是默认开启的。我们全局搜索一下“(BUILD_PREBUILT) ”会发现很多结果,这也就是为什么默认odex都开了,为什么开机并没有觉得快的原因了。
因此我们在做odex优化的时候,都会关闭DONT_DEXPREOPT_PREBUILTS,然后重新给我们预置的App添加
LOCAL_DEX_PREOPT :=false
让它们不进行预编译,这样也就能节省一些不必要的空间消耗。同时因为关闭了DONT_DEXPREOPT_PREBUILTS,很多可以随ROM升级的系统App也就进行了预编译,因此开机速度就有了明显的提高。
3、LOCAL_DEX_PREOPT
上面我们已经提到了,在App的Android.mk文件里面添加这个宏开关,可以控制这个App时候要预编译。一般预置的第三方App都会把这个宏开关置为false,这样既可以避免提取odex出现异常导致App功能异常,也能节省一定空间消耗。
LOCAL_DEX_PREOPT := false // 不进行预先优化LOCAL_DEX_PREOPT := true // 进行预先优化
提取odex错误例子:
这个时候就要在CallerIDHAER的Android.mk文件里面添加: LOCAL_DEX_PREOPT := false
4、WITH_DEXPREOPT_BOOT_IMG_ONLY
这个开关只是把boot image 进行预先优化。简单来说,其主要生成boot.art 和boot.oat。这能显著的减少systemimage 大小。但是,所有的app 都需要在第一次启动的时候进行优化需要花更长的boottime 时间。我们一般不配置这个开关。
5、WITH_DEXPREOPT_PIC
ART 在system 有一份OAT file,在运行时也会copy 一份到/data/ dalvik-cache下。如果我们内部存储不够,可以打开这个选项,但是这个选项可能会影响运行时的性能。因为ART 会关闭和position相关的优化。这个开关我们一般也不需要配置。
6、WITH_ART_SMALL_MODE
如果手机没有足够的空间,我们可以打开 这个宏。ART只会预先优化boot class。第一次启动的时间会大大的提升,但是也会大大影响运行时性能。因为其它的appcode 是解释性执行的。但这个开关是老版本的,现在新版本的Android版本一般不用关注。