Android L

(Android Lollipop、棒棒糖)是Googlek开发的第五个主要的Android系统,Android Lollipop首次亮相于2014年6月25日的

Google I/O开发者大会。为改善应用程序性能以ART模式正式取代了Dalvik虚拟机。从Android 5.0版起,Android Runtime(ART)取代Dalvik成为系统内默认虚拟机。

Dalvik vs JVM

大多数虚拟机包括JVM都是一种堆栈机器,而Dalvik虚拟机则是寄存器机。两种架构各有优劣,一般而言,基于堆栈的机器需要更多指令,而基于寄存器的机器指令更长。

ART vs Dalvik

ART能够把应用程序的字节码转换为机器码,是Android所使用的一种新的虚拟机。它与Dalvik的主要不同在于:Dalvik采用的是JIT技术,而ART采用Ahead-of-time(AOT)技术。在应用程序安装的过程中,ART会在安装APK的时候,使用Android系统自带的dex2oat工具把APK里面的.dex文件转化成OAT文件,OAT文件是一种Android私有ELF文件格式,它不仅包含有从DEX文件翻译而来的本地机器指令,还包含有原来的DEX文件内容。因此,ART极大的提高了应用程序的运行效率,同时也减少了手机的电量消耗,提高了移动设备的续航能力,在垃圾回收等机制上也有了较大的提升。

为了保证向下兼容,ART使用了相同的Dalvik字节码文件(dex),即在应用程序目录下保留了dex文件供旧程序调用然而.odex文件则替换成了可执行与可链接格式(ELF)可执行文件(oat)。一旦一个程序被ART的dex2oat命令编译,那么这个程序将会通过ELF可执行文件来运行。因此,相对于Dalvik虚拟机模式,ART模式下Android应用程序的安装需要消耗更多的时间,同时也会占用更大的储存空间(指内部储存,用于储存编译后的代码),但节省了很多Dalvik虚拟机用于实时编译的时间。

ART缺点:

1)机器码占用的存储空间更大

2)应用的安装时间会变长

tips:

现在智能手机大部分都可以让用户选择使用Dalvik还是ART模式。当然默认还是使用Dalvik模式。

用法:

设置-辅助功能-开发者选项(开发人员工具)-选择运行环境(不同的手机设置的步骤可能不一样)。

odex vs oat

ODEX,全名Optimized DEX,即优化过的DEX。

OAT文件本质上是一个ELF文件,因此在最外层它具有一般ELF文件的结构,例如它有标准的ELF文件头以及通过段(Section)来描述文件内容。OAT文件包含有两个特殊的段oatdata和oatexec,前者包含有用来生成本地机器指令的dex文件内容,后者包含有生成的本地机器指令,它们之间的关系通过储存在oatdata段前面的oat头部描述。

ART : .dex->.odex(机器码)(AOT  Ahead-Of-Time)

Dalvik: .dex->.odex(字节码)(JIT Just-In-Time)

机器码可直接执行,而字节码每次启动都需要执行将优化过的odex字节码再转换成机器码。

why odex ?

dex文件的数据是压缩的,文件头也不保证是词对齐的。这些问题可以通过不压缩直接保存为classes.dex和填充zip文件来解决,但会导致数据网络间传输的包体积变大。

我们需要在使用前把zip包里的classes.dex解压。当我们拿到文件的时候,我们可能还会做些之前提到的其他操作(对齐、优化、验证。这又引出了另一个问题:谁去负责做这些,我们又该把输出放在哪儿?

dexopt vs dex2oat

dexopt函数定义在frameworks/native/cmds/installd/commands.c中 函数dexopt首先是读取系统属性persist.sys.dalvik.vm.lib的值,接着在/data/dalvik-cache目录中创建一个odex文件。这个odex文件就是作为dex文件优化后的输出文件。再接下来,函数dexopt通过fork来创建一个子进程。如果系统属性persist.sys.dalvik.vm.lib的值等于libdvm.so,那么该子进程就会调用函数run_dexopt来将dex文件优化成odex文件。另一方面,如果系统属性persist.sys.dalvik.vm.lib的值等于libart.so,那么该子进程就会调用函数run_dex2oat来将dex文件翻译成oat文件,实际上就是将dex字节码翻译成本地机器码,并且保存在一个oat文件中。

函数run_dexopt通过调用/system/bin/dexopt来对dex字节码进行优化,而函数run_dex2oat通过调用/system/bin/dex2oat来将dex字节码翻译成本地机器码。注意,无论是对dex字节码进行优化,还是将dex字节码翻译成本地机器码,最终得到的结果都是保存在相同名称的一个odex文件里面的,但是前者对应的是一个odex文件(表示这是一个优化过的dex),后者对应的是一个oat文件(实际上是一个自定义的elf文件)。通过这种方式,原来任何通过绝对路径引用了该odex文件的代码就都不需要修改了。

原文链接:https://www.jianshu.com/p/389911e2cdfb

在Android 2.3版本以前,系统源码中提供了生成odex的工具dexopt-wrapper,位于Android 2.2系统源码的 build/tools/dexpreopt/dexopt-wrapper/ 目录下,查看DexOptWrapper.cpp文件会发现实际调用的是 /system/bin/dexopt 程序。在5.0及以上版本的设备上,你可能已经再也找不到dexopt了,取而代之的是dex2oat。

我们想要验证和优化DEX文件里的所有类。最简单和安全的方法就是把所有类加载到虚拟机,然后跑一遍。任何加载失败的就是验证/优化失败的。不幸的是,这可能导致一些资源的分配难以释放(比如native共享库的加载),所以我们不想执行在应用运行的虚拟机里。

解决方案就是起一个叫做dexopt的程序(事实上就是虚拟机的后门)。它会执行一个简短的虚拟机初始化,从引导的类路径加载0个或多个DEX文件,然后开始做一切从目标DEX可以做的验证和优化,最后生成一个odex文件。结束后,进程退出,释放所有资源。

因为多个虚拟机可能同时需求同一个DEX文件,文件锁被用来确保dexopt仅被执行一次。

原文链接:http://blog.zhaiyifan.cn/2016/02/24/android-reverse-3/

results matching ""

    No results matching ""