android的dex,odex,oat,vdex,art文件格式
dex文件格式
dex是android虚拟机的可执行字节码文件,java文件经过javac编译成class文件,class文件又被dx处理后生成dex文件。
dex文件分为四大部分: DEX文件头,索引结构区,data数据区,静态链接数据区。
所有的代码和数据都放在data数据区中,索引结构区中存放的是data中各种数据的对应的偏移和索引。
利用010查看一个dex文件的信息,可以发现此文件并没有静态链接数据区。
odex和oat格式
-
在android4.4之前,android为了优化程序执行效率使用的是JIT(just-in-time)即时编译,也就是程序运行时编译。因为apk文件是一个zip压缩包的格式,每次系统启动程序时都需要从apk中读取dex文件并加载执行,为了减少程序启动时从apk读取dex文件所需要的,android在apk第一次安装的时候dexopt将程序的dex文件进行优化生成odex文件,并将其放在了/data/dalvik-cache目录下。等下次apk启动时直接加载这个目录中经过优化的odex文件减少启动所需要的时间(优化基于当前系统的dalvik虚拟机版本,不同版本上的odex文件无法进行兼容)。在程序运行时android虚拟机会对一些执行频率较高的热点函数进行jit编译生成对应的本地代码,下次再执行此函数的时候直接执行对应的本地代码提高了执行的效率,注意jit编译的代码只会存在于内存中并不会持久化保存再磁盘中,下次启动apk后执行此函数还需要解释执行。
-
在android4.4之后,android使用的是AOT(Ahead-of-time)事前编译,也就是程序在运行前先编译。oat是ART虚拟机运行的文件,是ELF格式二进制文件,包含DEX和编译的本地机器指令,oat文件包含DEX文件,因此比ODEX文件占用空间更大。
程序在首次安装的时候,dex2oat默认会把classes.dex编译成本地机器指令,生成ELF格式的OAT文件,并将其放在了/data/dalvik-cache或者是/data/app/packagename/目录下。ART加载OAT文件后不需要经过处理就可以直接运行,它在编译时就从字节码装换成机器码了,因此运行速度更快。不过android4.4之后oat文件的后缀还是odex,但是已经不是android4.4之前的文件格式,而是ELF格式封装的本地机器码.可以认为oat在dex上加了一层壳,可以从oat里提取出dex.
因为此时的oat文件是一个标准的elf文件,识别其是不是oat文件的标准就是看其符号表。
-
oatdata指向的是ELF文件的.rodata节区,存放了OAT文件头OATHeader,OAT的DEX文件头,原始DEX文件的DexFile等信息。
-
oatexec指向的是ELF文件的.text节区,这里存放的是编译生成的指定平台的二进制代码。
-
oatlastword指向的是对应oat文件的结尾。
vdex文件格式
在android8.0(Android O)之前dex文件嵌入到oat文件本身中,在Android 8.0之后dex2oat将classes.dex优化生成两个文件oat文件(.odex)和vdex文件(.vdex)
- odex文件中包含了本机代码的OAT
- vdex文件包含了原始的DEX文件副本
art文件格式
ART虚拟机在执行dex文件时,需要将dex文件中使用的类,字符串等信息转换为自定义的结构。art文件就是保存了apk中使用的一些类,字符串等信息的ART内部表示,可以加快程序启动的速度。
参考:
https://lief-project.github.io/doc/latest/tutorials/10_android_formats.html#oat-and-vdex
https://m.eefocus.com/embedded/525061