WITH_DEXPREOPT
是否对系统映像上安装的 DEX 代码调用 dex2oat。默认处于启用状态。
DONT_DEXPREOPT_PREBUILTS(Android 5 及更高版本)
启用 DONT_DEXPREOPT_PREBUILTS 可防止对预构建应用进行 dexpreopt。这些都是在 Android.mk 中指定了 include $(BUILD_PREBUILT) 的应用。如果不对这些可能要通过 Google Play 更新的预构建应用进行 dexpreopt,可以节省系统映像内的空间,但是会增加首次启动时间。请注意,此选项对 Android.bp 中定义的预构建应用没有任何影响。
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER(Android 9 及更高版本)
PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER 为经过 dexpreopt 的应用指定默认编译器过滤器。这些都是 Android.bp 中定义或在 Android.mk 中指定了 include $(BUILD_PREBUILT) 的应用。如果未指定,则默认值为 speed-profile;如果未指定值且未提供配置文件,则值为 verify。
WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY(从 Android 8 MR1 开始)
如果启用 WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY,将只会对启动类路径和系统服务器 JAR 进行 dexpreopt。
LOCAL_DEX_PREOPT
通过在模块定义中指定 LOCAL_DEX_PREOPT 选项,还可以针对个别应用启用或停用 dexpreopt。这有助于避免对那些可能会立即收到 Google Play 更新的应用进行 dexpreopt,因为更新之后,对系统映像中的代码所做的 dexpreopt 都会变为无用功。此外,这还有助于在进行重大版本 OTA 升级时节省空间,因为用户的数据分区中可能已经有了更高版本的应用。
LOCAL_DEX_PREOPT 支持分别使用值 true 或 false 来启用或停用 dexpreopt。此外,如果在 dexpreopt 过程中不应将 classes.dex 文件从 APK 或 JAR 文件中剥离出来,则可以指定 nostripping。通常情况下,该文件会被剥离出来,因为在进行 dexpreopt 之后将不再需要该文件;但若要使第三方 APK 签名仍保持有效,则必须使用最后这个选项。
PRODUCT_DEX_PREOPT_BOOT_FLAGS
将选项传递给 dex2oat 以控制如何编译启动映像。该选项可用于指定自定义映像类列表、已编译类列表,以及编译过滤器。
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
将选项传递给 dex2oat 以控制如何编译除启动映像之外的所有内容。
PRODUCT_DEX_PREOPT_MODULE_CONFIGS
用于为特定模块和产品配置传递 dex2oat 选项。该选项在产品的 device.mk 文件中通过 $(call add-product-dex-preopt-module-config,
PRODUCT_DEXPREOPT_SPEED_APPS(从 Android 8 开始)
一个应用列表,其中的应用被确定为产品的核心应用,并且应使用 speed 编译器过滤器进行编译。例如,常驻应用(如 SystemUI)只有在下次系统重新启动时才有机会使用配置文件引导的编译,因此可能最好是让产品始终对这些应用进行 AOT 编译。
PRODUCT_SYSTEM_SERVER_APPS(从 Android 8 开始)
系统服务器加载的应用的列表。这些应用默认使用 speed 编译器过滤器进行编译。
PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD(从 Android 8 开始)
是否在设备上包含 ART 的调试版本。默认情况下,系统会针对 userdebug build 和 eng build 启用此选项。可以通过将该选项明确设为 true 或 false 来覆盖此行为。
默认情况下,设备将使用非调试版本 (libart.so)。如需进行切换,请将系统属性 persist.sys.dalvik.vm.lib.2 设置为 libartd.so。
WITH_DEXPREOPT_PIC(在 Android 7 之前)
从 Android 5.1.0 到 Android 6.0.1 的所有版本中,都可以指定 WITH_DEXPREOPT_PIC 来启用位置无关代码 (PIC)。这样一来,就不必将来自映像的编译代码从 /system 迁移到 /data/dalvik-cache,因此可以节省 data 分区中的空间。不过,因为该选项会停用根据位置相关代码进行的优化,所以会对运行时产生轻微的影响。通常情况下,需要节省 /data 空间的设备应启用 PIC 编译。
在 Android 7.0 中,PIC 编译默认处于启用状态。
WITH_DEXPREOPT_BOOT_IMG_ONLY(在 Android 7 MR1 之前)
此选项已被 WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY 取代,后者还会预先优化系统服务器 JAR。
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
此选项可指定系统服务器的编译过滤器。
(Android 14 及更高版本)如果未指定,则使用 speed-profile 编译过滤器;如果未提供配置文件,则使用 speed 编译过滤器。
(Android 13 及更低版本)如果未指定,则使用 speed 编译过滤器。
如果设置为 speed,则使用 speed 编译过滤器。
如果设置为 speed-profile,则使用 speed-profile 编译过滤器;如果未提供配置文件,则使用 verify 编译过滤器。
如果设置为 verify,则使用 verify 编译过滤器。
PRODUCT_SYSTEM_SERVER_JARS、PRODUCT_APEX_SYSTEM_SERVER_JARS、PRODUCT_STANDALONE_SYSTEM_SERVER_JARS、PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
以下是系统服务器加载的 JAR 的列表。JAR 使用由 PRODUCT_SYSTEM_SERVER_COMPILER_FILTER 指定的编译过滤器进行编译
(必需)PRODUCT_SYSTEM_SERVER_JARS:平台上的系统服务器类路径 JAR 的列表(即作为 SYSTEMSERVERCLASSPATH 的一部分)。需要将系统服务器类路径 JAR 添加到此列表。如果未能将系统服务器类路径 JAR 添加到此列表,会导致这些 JAR 无法加载。
(必需)PRODUCT_APEX_SYSTEM_SERVER_JARS:通过 APEX 传递的系统服务器类路径 JAR 的列表(即作为 SYSTEMSERVERCLASSPATH 的一部分)。格式为
(可选,Android 13 及更低版本)
PRODUCT_STANDALONE_SYSTEM_SERVER_JARS:系统服务器使用单独的类加载器动态加载(通过 SystemServiceManager.startServiceFromJar)的 JAR 的列表。无需将独立系统服务器 JAR 添加到此列表,但强烈建议您这样做,原因是这会使 JAR 经过编译,因此 JAR 将具有良好的运行时性能。
(必需,从 Android 13 开始)
PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS:通过 APEX 传递且系统服务器使用单独的类加载器动态加载(即通过 SystemServiceManager.startServiceFromJar 或声明为
启动类路径配置
预加载的类列表列出了 Zygote 在启动时初始化的类。利用该列表,每个应用无需单独运行这些类初始化程序,从而可以更快地启动并共享内存中的页面。预加载的类列表文件默认位于 frameworks/base/config/preloaded-classes,其中包含一个针对典型手机使用场景优化的列表。此列表可能不适用于其他设备(如穿戴式设备),必须进行相应调整。做调整时要格外小心;添加的类太多会造成加载未用到的类而浪费内存,而添加的类太少又会导致每个应用都各有一份副本,同样会造成内存浪费。
使用示例(在产品的 device.mk 中):
PRODUCT_COPY_FILES +=
注意:如果有任何从 build/target/product/base.mk 提取默认值的产品配置 makefile,则此行必须放置在沿用任何这类 makefile 的行之前。
运行时配置
JIT 选项
仅在 ART JIT 编译器可用的情况下,以下选项才会影响 Android 版本。
dalvik.vm.usejit:是否启用 JIT。
dalvik.vm.jitinitialsize(默认为 64K):代码缓存的初始容量。代码缓存将定期进行垃圾回收 (GC),并将视需要增加容量。
dalvik.vm.jitmaxsize(默认为 64M):代码缓存的最大容量。
dalvik.vm.jitthreshold(默认为 10000):方法的“热度”计数器必须超过该阈值,系统才会对方法进行 JIT 编译。“热度”计数器是运行时的内部指标。它的影响因素包括调用次数、后向分支及其他因素。
dalvik.vm.usejitprofiles(在 Android 13 之前):是否启用 JIT 配置文件;即使 dalvik.vm.usejit 为 false,也可以使用该选项。请注意,如果该选项为 false,编译器过滤器 speed-profile 将不会对任何方法进行 AOT 编译,效果与 verify 相同。从 Android 14 开始,JIT 配置文件始终处于启用状态,并且无法关闭。
dalvik.vm.jitprithreadweight(默认为 dalvik.vm.jitthreshold / 20):应用界面线程的 JIT“样本”(请参阅 jitthreshold)的权重。用于加快以下方法的编译速度:当用户与应用交互时,会直接影响用户体验的方法。
dalvik.vm.jittransitionweight(默认为 dalvik.vm.jitthreshold / 10):调用时需要在编译代码和解译器之间进行转换的方法的权重。这有助于确保对所涉及的方法进行编译以尽可能减少转换(转换需要很大开销)。
Dex2oat 选项
这些选项会影响设备端编译(又称为 dexopt),其中几个选项还会影响 dexpreopt,而上文系统 ROM 配置部分中所述的选项只会影响 dexpreopt。
用于控制资源使用情况的选项:
dalvik.vm.image-dex2oat-threads/dalvik.vm.image-dex2oat-cpu-set(在 Android 11 之前):用于启动映像的线程数量和 CPU 核心组(见下文)。
dalvik.vm.boot-dex2oat-threads/dalvik.vm.boot-dex2oat-cpu-set:
(在 Android 11 之前)在启动期间用于除启动映像外所有其他内容的线程数量和 CPU 核心组(见下文)。
(从 Android 12 开始)在启动期间用于所有内容(包括启动映像)的线程数量和 CPU 核心组(见下文)。
具体而言,从 Android 14 开始,这与 ART 服务中的优先级类 PRIORITY_BOOT 对应。
dalvik.vm.restore-dex2oat-threads/dalvik.vm.restore-dex2oat-cpu-set:
(从 Android 11 到 Android 13)从云端备份恢复所用的线程数量和 CPU 核心组(见下文)。
(从 Android 14 开始)用于比正常情况对延迟更敏感的所有操作(包括从云端备份恢复)的线程数量和 CPU 核心组(见下文)。
具体而言,这与 ART 服务中的优先级类 PRIORITY_INTERACTIVE_FAST 对应。
dalvik.vm.background-dex2oat-threads/dalvik.vm.background-dex2oat-cpu-set(从 Android 14 开始):在后台使用的线程数量和 CPU 核心组(见下文)。
具体而言,这与 ART 服务中的优先级类 PRIORITY_BACKGROUND 对应。
dalvik.vm.dex2oat-threads/dalvik.vm.dex2oat-cpu-set:用于所有其他操作的线程数量和 CPU 核心组。
指定 CPU 核心组时,应采用以英文逗号分隔的 CPU ID 列表的形式。例如,如需在 CPU 核心 0-3 上运行 dex2oat,请按如下所示进行设置:
dalvik.vm.dex2oat-cpu-set=0,1,2,3
设置 CPU 亲和性属性时,建议设定 dex2oat 线程数量的相应属性与选定的 CPU 的数量相匹配,以避免不必要的内存和 I/O 争用:
dalvik.vm.dex2oat-cpu-set=0,1,2,3
dalvik.vm.dex2oat-threads=4
除了上述系统属性之外,您还可以使用任务配置文件来控制 dex2oat 的资源使用情况(请参阅 Cgroup 抽象层)。
支持的任务配置文件包括:
Dex2OatBackground(从 Android 14 开始)(默认情况下继承 Dex2OatBootComplete):控制在后台使用的资源。
具体而言,这与 ART 服务中的优先级类 PRIORITY_BACKGROUND 对应。
Dex2OatBootComplete:
(在 Android 13 之前)控制要用于启动后的所有操作的资源。
(从 Android 14 开始)控制要用于启动后的所有非后台运行操作的资源。
具体而言,这与 ART 服务中的优先级类 PRIORITY_INTERACTIVE_FAST 和 PRIORITY_INTERACTIVE 对应。
如果同时指定了系统属性和任务配置文件,则两者都会生效。
用于控制堆大小的选项:
dalvik.vm.image-dex2oat-Xms:启动映像的初始堆大小。
dalvik.vm.image-dex2oat-Xmx:启动映像的堆大小上限。
dalvik.vm.dex2oat-Xms:所有其他内容的初始堆大小。
dalvik.vm.dex2oat-Xmx:所有其他内容的堆大小上限。
不应减小用于控制 dex2oat 初始堆大小和堆大小上限的选项数值,因为它们可能会限制可对哪些应用进行编译。
用于控制编译器过滤器的选项:
dalvik.vm.image-dex2oat-filter(在 Android 11 之前):启动映像的编译器过滤器。从 Android 12 开始,启动映像的编译器过滤器始终为 speed-profile,并且无法更改。
dalvik.vm.systemservercompilerfilter(从 Android 13 开始):系统服务器的编译器过滤器。请参阅 PRODUCT_SYSTEM_SERVER_COMPILER_FILTER。
dalvik.vm.systemuicompilerfilter(从 Android 13 开始):系统界面包的编译器过滤器。
dalvik.vm.dex2oat-filter(在 Android 6 之前):所有其他内容的编译器过滤器。
pm.dexopt.
用于控制除启动映像外的所有其他内容的编译的其他选项:
dalvik.vm.dex2oat-very-large(从 Android 7.1 开始):停用 AOT 编译的最小总 dex 文件大小(以字节为单位)。
dalvik.vm.dex2oat-swap(从 Android 7.1 开始)(默认值:true):允许为 dex2oat 使用交换文件。这有助于避免内存不足崩溃。请注意,即使此选项已开启,dex2oat 也只会在特定条件下(例如 dex 文件数量很多)使用交换文件,条件可能会发生变化。
dalvik.vm.ps-min-first-save-ms(从 Android 12 开始):在运行时生成应用配置文件(应用首次启动)之前等待的最短时间。
dalvik.vm.ps-min-save-period-ms(从 Android 12 开始):更新应用配置文件之前等待的最短时间。
dalvik.vm.dex2oat64.enabled(从 Android 11 开始)(默认值:false):是否使用 64 位版本的 dex2oat。
dalvik.vm.bgdexopt.new-classes-percent(从 Android 12 开始)(默认值:20):配置文件中用于触发重新编译的新类的最小百分比(0 到 100 之间)。仅适用于配置文件引导的编译 (speed-profile),通常在后台 dexopt 运行期间。请注意,除了百分比阈值之外,系统还会创建“至少 50 个新类”阈值,并且该阈值不可配置。
dalvik.vm.bgdexopt.new-methods-percent(从 Android 12 开始)(默认值:20):配置文件中用于触发重新编译的新方法的最小百分比(0 到 100 之间)。
仅适用于配置文件引导的编译 (speed-profile),通常在后台 dexopt 运行期间。请注意,除了百分比阈值之外,系统还会创建“至少 100 个新方法”阈值,并且该阈值不可配置。
dalvik.vm.dex2oat-max-image-block-size(从 Android 10 开始)(默认值:524288)压缩图片的实心块大小上限。系统会将一张大图片拆分为一组实心块,确保实心块不超过大小上限。
dalvik.vm.dex2oat-resolve-startup-strings(从 Android 10 开始)(默认值:true)如果为 true,则会导致 dex2oat 解析配置文件中标记为“startup”的方法引用的所有常量字符串。
debug.generate-debug-info(默认值:false)是否要为原生调试生成调试信息,例如堆栈展开信息、ELF 符号和 dwarf 部分。
dalvik.vm.dex2oat-minidebuginfo(从 Android 9 开始)(默认值:true)是否生成输出回溯所需的最少量的 LZMA 压缩调试信息。
ART 服务选项
从 Android 14 开始,应用的设备端 AOT 编译(又称为 dexopt)由 ART 服务处理。如需了解如何配置 ART 服务,请参阅 ART 服务配置。
软件包管理系统选项
在 Android 14 之前,应用的设备端 AOT 编译(又称为 dexopt)由软件包管理系统处理。如需了解如何为 dexopt 配置软件包管理系统,请参阅软件包管理系统配置。
A/B 专有配置
ROM 配置
从 Android 7.0 开始,设备可以使用两个 system 分区来实现 A/B 系统更新。为了减小 system 分区大小,可以将经过预先优化的文件安装在未使用的第二个 system 分区中。在系统首次启动时,这些文件会被复制到 data 分区。
使用示例(在 device-common.mk 中):
PRODUCT_PACKAGES += \
cppreopts.sh
PRODUCT_PROPERTY_OVERRIDES += \
ro.cp_system_other_odex=1
在设备的 BoardConfig.mk 中:
BOARD_USES_SYSTEM_OTHER_ODEX := true
请注意,启动类路径代码、系统服务器代码以及产品专属的核心应用始终会被编译到系统分区中。默认情况下,所有其他应用都会被编译到未使用的第二个系统分区中。可以使用 SYSTEM_OTHER_ODEX_FILTER 控制此行为,其值默认为:
SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%
后台 OTA dexopt
在启用了 A/B 的设备上,在使用新的系统映像重新启动之前,可以在后台编译应用。如需在系统映像中选择性地加入编译脚本和二进制文件,请参阅在后台编译应用。可通过以下选项控制用于此类编译的编译器过滤器:
pm.dexopt.ab-ota=speed-profile
我们建议使用 speed-profile,以利用配置文件引导的编译并节省存储空间。
JDWP 选项
persist.debug.dalvik.vm.jdwp.enabled 系统属性用于控制是否在 userdebug build 中创建 Java 调试网络协议 (JDWP) 线程。默认情况下,系统不会设置此属性,且系统只会为可调试应用创建 JDWP 线程。如需同时为可调试和不可调试应用启用 JDWP 线程,请将 persist.debug.dalvik.vm.jdwp.enabled 设为 1。必须重新启动设备,才能使属性更改生效。
如需在 userdebug build 中调试某个不可调试应用,请运行以下命令来启用 JDWP:
adb shell setprop persist.debug.dalvik.vm.jdwp.enabled 1
adb reboot
注意:将 persist.debug.dalvik.vm.jdwp.enabled 属性设为 1,这不会使应用变得可调试,而只会允许将调试程序附加到进程。
对于搭载 Android 13 或更低版本的设备,运行时会在 userdebug build 中为可调试和不可调试应用创建 JDWP 线程。这意味着,您可以在 userdebug build 中附加调试程序或分析应用性能。