一同事在修改了package/app下面的工程之后,不想full build于是直接mm之后 找到APK直接adb install报错如下
Failure [INSTALL_FAILED_DEXOPT]
先来说说问题产生的原因。
如果我们在user版本用mm编译apk时,会在out目录下生成.apk和.odex两个文件,是为了加快运行速度,把dex分出来做的预优化处理。但是一般开发时需要mm编译出一个完整的apk,直接用adb进行安装就可以进行调试。这样的话我们有两个选择,一个选择是切到非user版本坐编译 ,另外一种方案就是在当前的需要编译的app目录的.mk文件中加入如下代码关闭对于当前APK的预优化处理即可:
LOCAL_DEX_PREOPT := false
那么为什么user版本会对apk进行预优化处理呢,在device.mk里面 或者device下面别的.mk文件里面会有如下代码:
ifeq ($(TARGET_BUILD_VARIANT), user)
ifeq ($(WITH_DEXPREOPT),)
WITH_DEXPREOPT ?= true
那么在user版本下 WITH_DEXPREOPT会是true.而WITH_DEXPREOPT决定了LOCAL_DEX_PREOPT的值。
那么问题又来了,什么是预优化,预优化的原理是什么,预优化的有什么好处呢,带着这些问题来看看。
首先,什么是预优化。
对于Android而言,预优化也就是把Android在launch或者runtime时候所需要做的一些事儿,把这些事儿提前到编译期来达到Android启动速度的加速和APP运行速度的加速。
然后Android预优化的原理。
在5.0之前 Android一直用的DVM虚拟机,到了5.0换成了ART。
咦,怎么突然说起了虚拟机,别急,我们先来看看Java几种虚拟机的工作机制:
(1)JVM:JVM虚拟机运行的是java字节码。Java文件到JVM的过程是:java -> java bytecode(class) -> java bytecode(jar)。
(2)DVM:DVM虚拟机解析执行的dex字节码。Java文件到DVM的过程是:java -> java bytecode(class) -> dalvik bytecode(dex)。
(3)ART:ART虚拟机执行本地机器码。Java文件到ART的过程是:java -> java bytecode(class) -> dalvik bytecode(dex) -> optimized android runtime machine code(oat)。
我们能看到,从java文件到虚拟机执行代码,ART比DVM多了OAT的过程。
ART所使用的AOT(Ahead-Of-Time) 编译,在首次安装应用的时候,字节码预编译成机器码存在本地。
DVM是典型的JIT(Just-In-Time) ,在此模式下,应用每次运行的时候,字节码都需要即时的编译转换成机器码再执行。
那么对于ART而言就省去了解析字节码的过程,占用内存也会相应的减少,从而提升APP的运行效率。