Android中dex文件的加载与优化流程

原创 2016年08月03日 14:50:46

目录

1、dex文件分析...1

2、odex文件...2

2.1、odex文件结构...2

2.2、odex文件结构分析...3

3、dex文件的验证与优化...3

3.1 dex文件加载流程...3

3.2 dex文件优化加载流程图...4

 

1、dex文件分析

逻辑上,可以把dex文件分成3个区,头文件、索引区和数据区。索引区的ids后缀为identifiers的缩写。


header

dex文件里的header。除了描述.dex文件的文件信息外,还有文件里其他各个区域的索引。


(1)           magic value,这8个字节一般是常量,为了使.dex文件能够被识别出来,它必须出现在.dex文件的最开头的位置。

(2)           checksum和signature.文件校验码,使用alder32算法校验文件出去maigc,checksum外余下的所有文件区域,用于校验文件错误。Signature,使用SHA-1算法hash除去magic,checksum和signature外余下的所有文件区域。

(3)           file_size:Dex文件的大小。

其余的属性,因为在加固中没有用到。这里就不对它们进行过多解释。

2、odex文件

odex是OptimizedDEX的缩写,表示经过优化的dex文件。存放在/data/dalvik-cache目录下。由于Android程序的apk文件为zip压缩包格式,Dalvik虚拟机每次加载它们时需要从apk中读取classes.dex文件,这样会耗费很多cpu时间,而采用odex方式优化的dex文件,已经包含了加载dex必须的依赖库文件列表,Dalvik虚拟机只需检测并加载所需的依赖库即可执行相应的dex文件,这大大缩短了读取dex文件所需的时间。

不过,这个优化过程会根据不同设备上Dalvik虚拟机的版本、Framework库的不同等因素而不同。在一台设备上被优化过的ODEX文件,拷贝到另一台设备上不一定能够运行。

2.1、odex文件结构

Odex文件的结构可以理解为dex文件的一个超集。它的结构如下图所示,odex文件在dex文件头部添加了一些数据,然后在dex文件尾部添加了dex文件的依赖库以及一些辅助数据。

 
 

 

 

 


Dalvik虚拟机将dex文件映射到内存中后是Dalvik格式,在Android系统源码的dalvik/libdex/DexFile.h文件中它的定义如下。

DexFile结构中存入的多为其他结构的指针。DexFile最前面的DexOptHeader就是odex的头,DexLink以下的部分被成为auxillary section,即辅助数据段,它记录了dex文件被优化后添加的一些信息。然而,DexFile结构描述的是加载进内存的数据结构,还有一些数据是不会加载进内存的,经过分析,odex文件结构定义整理如下.


Struct ODEXFile{

           DexOptHeader             header;    /*odex文件头*/

           DEXFile                          dexfile;  /*dex文件*/

           Dependences              deps;        /*依赖库列表*/

           ChunkDexClassLookup    lookup;     /*类查询结构*/

           ChunkRegisterMapPool          mappool; /*映射池*/

           ChunkEnd                            end;    /*结束标志*/

};

2.2、odex文件结构分析

         ODEXFile的文件头DexOptHeader在DexFile.h文件中定义如下.

struct DexOptHeader{

         u1  magic[8];                  /*odex版本标识 */

         u4  dexOffset;            /* dex文件头偏移*/

         u4  dexLength;      /* dex文件总长度*/

         u4  depsOffset;      /*odex依赖库列表偏移*/

         u4  depsLength;     /*依赖库列表总长度*/

         u4  optOffset;       /*辅助数据偏移*/

         u4  optLength;       /*辅助数据总长度*/

         u4  flags ;                          /*标志*/

         u4  checksum;        /*依赖库与辅助数据的校验和*/

};

3、dex文件的验证与优化

3.1 dex文件加载流程 

Android提供了一个专门验证与优化dex文件的工具dexopt。其源码位于Android系统源码的dalvik/dexopt目录下,Dalvik虚拟机在加载一个dex文件时,通过指定的验证与优化选项来调用dexopt进行相应的验证与优化操作。

         dexopt的主程序为OptMain.cpp,其中处理apk/jar/zip文件中的classes.dex的函数为extractAndProcessZip(),extractAndProcessZip()首先通过dexZipFindEntry()函数检查目标文件中是否拥有class.dex,如果没有就失败返回,成功的话就调用dexZipGetEntryInfo()函数来读取classes.dex的时间戳与crc校验值,如果这一步没有问题,接着调用dexZipExtractEntryTo-File()函数释放classes.dex为缓存文件,然后开始解析传递过来的验证与优化选项,验证选项使用“v=”指出,优化选项使用“o=”指出。所有的预备工作都做完后,调用dvmPrepForDexOpt()函数启动一个虚拟机进程,在这个函数中,优化选项dexOptMode与验证选项varifyMode被传递到了全局DvmGlobals结构gDvm的dexOptMode与classVerifyMode字段中。这时候所有的初始化工作已经完成,dexopt调用dvmContinueOptimization()函数开始真正的验证和优化工作。

         dvmContinueOptimization()函数的调用链比较长。首先从OptMain.cpp转移到、dalvik/vm/analysis/DexPrepare.cpp,因为这里有dvmContinueOptimization()函数的实现。函数首先对dex文件做简单的检查,确保传递进来的目标文件属于dex或odex,接着调用mmap()函数将整个文件映射到内存中,然后根据gDvm的dexOptMode与classVerifyMode字段来设置doVarify与doOpt两个布尔值,接着调用rewriteDex()函数来重写dex文件,这里的重写内容包括字符调整、结构重新对齐、类验证信息以及辅助数据。rewriteDex()函数调用dexSwapAndVerify()调整字节序,接着调用dvmDexFileOpenPartial()创建DexFile结构,dvmDexFileOpenPartial()函数的实现在Android系统源码dalvik/vm/DvmDex.cpp文件中,该函数调用dexFileParse()函数解析dex文件,dexFileParse()函数读取dex文件的头部,并根据需要调用验证dexComputeChecksum()函数或调用dexComputeOptChecksum()函数来验证dex或odex文件爱你头的checksum与signature字段。

         接着回到DvmDex.cpp文件继续看代码,当验证成功后,dvmDexFileOpenPartial()函数调用allocateAuxStructures()函数设置DexFile结构辅助数据的相关字段,最后执行完后返回到rewriteDex()函数。rewriteDex()接下来调用loadAllClasses()加载dex文件中所有的类,如果这一步失败了,程序等不到后面的优化与验证就退出了,如果没有错误发生,会调用verifyAndOptimizeClasses()函数进行真正的验证工作,这个函数会调用verifyAndOptimizeClass()函数来优化与验证具体的类,而verifyAndOptimizeClass()函数会细分这些工作,调用dvmVerifyClass()函数进行验证,再调用dvmOptimizeClass()函数进行优化。

         dvmVerifyClass()函数的实现代码位于Android系统源码的dalvik/vm/analysis/DexVerify.cpp文件中。这个函数调用verifyMethod()函数对类的所有直接方法与虚方法进行验证,verifyMethod()函数具体的工作是先调用verifyInstructions()函数来验证方法中的指令及其数据的正确性,再调用dvmVerifyCodeFlow()函数来验证代码流的正确性。

         dvmOptimizeClass()函数的实现代码位于Android系统源码的dalvik/vm/analysis/Optimize.cpp文件爱你中。这个函数调用optimizeMethod()函数对类的所有直接方法与虚方法进行优化,优化的主要工作是进行“指令替换”,替换原则的优先级为“volatile”替换-正确性替换-高性能替换。比如指令iget-wide会根据优先级替换为“volatile”形式的iget-wide-volatile,而不是高性能的iget-wide-quick.

         rewriteDex函数返回后,会再次调用dvmDexFileOpenPartial()来验证odex文件,接着调用dvmGenerateRegisterMaps()函数来填充辅助数据区结构,填充结构完成后,接下来调用updateChecksum()函数重写dex文件爱你的checksum值,再往下就是writeDependencies()与writeOptData()了。

3.2 dex文件优化加载流程图

 


版权声明:本文为博主原创文章,未经博主允许不得转载。

Android dex加载过程分析

啊啊啊啊啊啊啊,开始吧。 ClassLoader有两种,PathClassLoader和DexClassLoader public class DexClassLoader extends Base...
  • protoss_penguin
  • protoss_penguin
  • 2016年08月10日 22:30
  • 2600

Android 使用DexClassLoader来运行其他apk中的方法

DexClassLoader 装载其他程序的类
  • l2show
  • l2show
  • 2014年10月30日 15:00
  • 15564

dvm,art模式下的dex文件加载流程

dvm,art模式下的dex文件加载流程dex加载是学习android的重中之重,刚看完几篇参考博客,对应android源码,收益匪浅,用一篇博客总结一下自己学到的东西。1.dvm模式下的dex加载这...
  • m0_37344790
  • m0_37344790
  • 2017年11月13日 18:15
  • 62

Android内存加载Dex文件示例代码

  • 2017年11月06日 11:40
  • 8.13MB
  • 下载

android 动态加载jar/dex文件

最近一直在搞android动态加载这一块内容,感觉还是学会到了很多新的东西,下面就分享给大家。    熟悉java的朋友,肯定知道ClassLoader这个东西,我们可以使用ClassLoader去...
  • qiaobusiwolaile
  • qiaobusiwolaile
  • 2015年04月12日 21:45
  • 630

android的DEX文件和APK 加载

2.6.2 DEX 文件和APK 加载 在Android 中,对编译出来的DEX 字节码和APK 文件的加载过程,也进行了尽可能的优化。 对于预置应用,Android 会在系统编译后,生成...
  • taoxugang2012
  • taoxugang2012
  • 2013年10月09日 13:47
  • 1714

Android 一种在Dalvik虚拟机上多Dex加载优化的方案

在Android源码中,DexFile中有一个openDexFile方法,就是通过byte数组加载一个Dex,可以达到秒级加载,亲自测了下,如果一个使用Multidex加载的App,第二个Dex如果需...
  • sbsujjbcy
  • sbsujjbcy
  • 2016年11月28日 18:26
  • 2548

Android培训班(67)dex文件打开流程

从上面可知调用函数Dalvik_dalvik_system_DexFile_openDexFile来打开Dex文件,这个函数的源码如下:staticvoid Dalvik_dalvik_system_...
  • caimouse
  • caimouse
  • 2011年09月03日 21:46
  • 7341

Android培训班(66)dex文件打开流程

下面来分析这个函数代码,如下:intdexZipPrepArchive(int fd, const char* debugFileName, ZipArchive*pArchive){这个函数输入文件...
  • caimouse
  • caimouse
  • 2011年08月28日 09:26
  • 8872

Android内存动态加载Dex

  • 2017年11月23日 15:24
  • 38KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android中dex文件的加载与优化流程
举报原因:
原因补充:

(最多只允许输入30个字)