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

Android中dex文件的加载与优化流程目录1、dex文件分析…12、odex文件…22.1、odex文件结构…22.2、odex文件结构分析…33、dex文件的验证与优化…33.1dex文件加载流程…33.2dex文件优化加载流程图…4 1、dex文件分析逻辑上,可以把dex文件分成3个区,头文件、索引区和数据区。索引区的ids后缀为i

大家好,又见面了,我是你们的朋友全栈君。

目录

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的缩写。

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

header

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

Android中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文件的依赖库以及一些辅助数据。

 
 

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

 

 

 

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

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

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

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文件的加载与优化流程

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153553.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux解压gz.gz文件,linux解压tar.gz并重命名_linux解压tar.gz文件

    linux解压gz.gz文件,linux解压tar.gz并重命名_linux解压tar.gz文件原标题:linux解压tar.gz并重命名_linux解压tar.gz文件命名为jpg.tar.gztar–cjfjpg.tar.bz2*.jpg//将目录里所有jpg文件打包成jpg.tar后,并且将其需要先下载zipforlinux解压tar–xvffile.tar//解压tar包tar-xzvffile.tar.gz//解压tar.gztaCSDN提供了…

    2022年6月18日
    36
  • Linux如何添加路由_linux添加永久路由命令

    Linux如何添加路由_linux添加永久路由命令Linux如何添加路由a.如何使用命令给Linux添加一个默认网关?缺省网关路由:默认网关就是数据包不匹配任何的路由规则,最后流经的地址关口!网关按字面意思就是网络的关口,就相当于我们办公室的大门一样,大家上班就要经过办公室的门一样。使用route-n查看网关信息,或者netstat-rn查看路由[root@machine1~]#route-nKernel

    2022年9月27日
    4
  • #include<vector>

    #include<vector>

    2021年9月27日
    74
  • 记忆化搜索简介「建议收藏」

    记忆化搜索简介「建议收藏」记忆化搜索:算法上依然是搜索的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存。一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。

    2022年7月26日
    8
  • 基于ZigBee和STM32的智能家居控制系统的设计与实现(五)–终结篇

    基于ZigBee和STM32的智能家居控制系统的设计与实现(五)–终结篇说明首先祝贺自己顺利的完成了毕业答辩工作,想起整个过程还是挺让自己感动的。最后还被评为优秀毕业设计,虽然并没有什么luan用,但是,马上毕业了,还是挺让人怀念的。整个资料从第一篇博客说起就说会全部开源的,期间承蒙各位朋友的支持,给与资助,在此感谢了。虽然资料中私人信息删除了一些,但是不免有疏漏,所以有关个人信息还挺各位删除掉,小

    2022年4月8日
    45
  • pyspark 内容介绍(一)

    pyspark 内容介绍(一)

    2021年11月26日
    52

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号