android ART编译预优化

来源:互联网 发布:rsa算法加密解密过程 编辑:程序博客网 时间:2024/06/03 20:04

编译预优化

DEX文件编译比较花费时间。这在OTA或者工厂首次烧入程序后非常明显。

可以在BoardConfig.mk文件中使能编译预优化,在编译时将会为APK/jar做Dex优化(dex2oat):

[plain] view plain copy
  1. WITH_DEXPREOPT := true  

如果完全的编译预优化,则system.img的大小将会增加500MB。由于ASLR特性,预优化的DEX文件将被转化并拷贝到data分区,所以data分区同样增加500MB。

对于android 5.1,可以使用WITH_DEXPREOPT_PIC来禁止data分区中的优化文件,只在system分区存在编译预优化的文件,这会对运行时稍微有些影响,这可以通过在BoardConfig.mk中添加编译选项实现:

[plain] view plain copy
  1. WITH_DEXPREOPT := true  
  2. WITH_DEXPREOPT_PIC := true  
如果分区大小受限,则可以使用WITH_ART_SMALL_MODE参数减小编译预优化后的文件大小,这同样是在BoardConfig.mk文件中实现:

[plain] view plain copy
  1. WITH_DEXPREOPT := true  
  2. WITH_ART_SMALL_MODE := true  

WITH_ART_SMALL_MODE主要是将BootClasspath和大多数APKs用到的Jar文件做dex2oat转化,只做传统的解释优化。而不会为apk启动编译预先优化,这将加速首次系统启动,但也影响app运行时性能。但是影响是有限的,这一优化将增加200MB的系统分区大小。

在往后的版本中,该优化选项去掉了。使用如下:

[plain] view plain copy
  1. +WITH_DEXPREOPT := true  
  2. +PRODUCT_PROPERTY_OVERRIDES +=\  
  3. +               dalvik.vm.dex2oat-filter=interpret-only \  
  4. +               dalvik.vm.image-dex2oat-filter=speed  


编译预优化可能的问题

一类问题是64bit处理器上遇到的ABI的适用性问题。

共享UID问题

在64bit机器上共享UID非常复杂:

  • 在64bit机器上,32bit和64bit app都能运行,有两种Zygote进程:“Zygote”和“Zygote64”。“Zygote”用于fork 32bit应用进程,“Zygote64”用于fork 64bit进程。
  • 如果应用共享UID(在AndroidManifest.xml文件中使用android.shareUserId),尤其是当它们共享进程时(使用“android:process”指定app运行的目标进程),则所有的共享UID相同的进程必须运行在相同的进程中。
  • 只有不依赖JNI的apk,可以被同时编译成32bit和64bit。如果使能了编译预优化,在编译时将生成二进制文件。对于64bit机器,绝大多少apk默认将被编译成64bit二进制,在编译预优化完成后,为了节省空间apk的classes.dex将被删除,但是如果apk依赖native代码,并且native代码被编译成了32bit二进制,apk同样要被编译成32bit二进制。
  • 问题来了,如果一个32bit apk和一个64bit apk使用共享UID,这将导致未知问题。
  • 如果apk不共享UID,将不会出现问题。

有三种解决方法:

  • 对于所有共享相同UID的apk, 在编译的.mk文件中添加LOCAL_MULTILIB := both以支持两个版本的odex。
  • 在.mk文件中使用LOCAL_DEX_PREOPT := nostripping以确保classes.dex文件不被删除,这将节约存储空间,但是影响启动时间。
  • 创建伪link以使PackageManager运行在32bit模式,这通过将ystem/app/(appname)/lib/arm/通过符号链接到任意的32bit库。