目录

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

  1. Android 中LayoutInflater(布局加载器)之介绍篇

    本文出自博客Vander丶CSDN博客,如需转载请标明出处,尊重原创谢谢 博客地址:http://blog.csdn.net/l540675759/article/details/78099358 前 ...

  2. java web配置dll文件_JavaWeb项目中dll文件动态加载方法解析(详细步骤)

    相信很多做Java的朋友都有过用Java调用JNI实现调用C或C++方法的经历,那么Java Web中又如何实现DLL/SO文件的动态加载方法呢.今天就给大家带来一篇JAVA Web项目中DLL/SO ...

  3. Android中使用x5内核加载网页的实现

    前言 联系方式 背景 SDK下载 SDK集成 使用 代码实现 前言 由于是使用的腾讯浏览服务,所以这里大部分介绍的是官网的一些东西,不过自己会做一些复杂使用部分的实现,不至于像官网上介绍的笼统. 联系 ...

  4. 一文了解 Java 中 so 文件的加载原理

    前言 无论是 Android 开发者还是 Java 工程师应该都有使用过 JNI 开发,但对于 JVM 如何加载 so.Android 系统如何加载 so,可能鲜有时间了解. 本文通过代码.流程解释, ...

  5. vue项目中主要文件的加载顺序(index.html、App.vue、main.js)

    先后顺序: index.html > App.vue的export外的js代码 > main.js > App.vue的export里面的js代码 > Index.vue的ex ...

  6. django 中静态文件项目加载问题

    问题描述: django项目中创建了多个app后,每个app中都有对应的static静态文件.整个项目运行时这些静态文件的加载就是一个问题,因为整个项目我只参与了一部分,项目部署之类的并没有参与.我写 ...

  7. Android中常见的图片加载框架

    图片加载涉及到图片的缓存.图片的处理.图片的显示等.而随着市面上手机设备的硬件水平飞速发展,对图片的显示要求越来越高,稍微处理不好就会造成内存溢出等问题.很多软件厂家的通用做法就是借用第三方的框架进行 ...

  8. java中class文件如何加载的_jvm如何加载class文件

    编译期: javac是JDK自带的编译器, 可以将java文件编译为class字节码文件, javap是JDK自带的反编译器,将.class字节码反编译为.java文件,javap -help是jav ...

  9. Springboot中属性文件的加载和生效顺序

    1.先读取的属性不一定先生效. 2.属性文件的读取顺序:JAVA SE运行时系统属性(启动命令中-D参数指定的属性)>系统环境变量属性>bootstrap属性>application ...

最新文章

  1. 程序员这样面试,拿到offer的几率是90%!
  2. kivy python 读取oracle数据库_Kivy和Python线程-如何在它们之间获取数据
  3. null?对象?异常?到底应该如何返回错误信息
  4. word邮件合并一页8个_办公软件小课堂||word邮件合并
  5. 4.关于QT中的QFile文件操作,QBuffer,Label上添加QPixmap,QByteArray和QString之间的区别,QTextStream和QDataStream的区别,QT内存映射(
  6. 【蓝桥杯Java_C组·从零开始卷】第六节(一)、Java常用数学函数
  7. android oneshot自动播放bug,移动端常见bug汇总001
  8. 如何卸载IE7重装IE6
  9. brew update失败提示:/System/Library/Frameworks/Ruby.framework/。。。解决方法
  10. Springboot — 用更优雅的方式发HTTP请求(RestTemplate详解)
  11. shell倒数第三位增加字符_shell中常用的变量处理、字符串操作(之三)
  12. 大数据之spark_spark SQL的建表语句
  13. GPS原理与接收机————GPS信号及其导航电文
  14. js——分享QQ、QQ空间、微信、微博
  15. gitee免费部署静态网站
  16. java url链接超时_Java编程中HttpURLConnection的连接超时中的异常
  17. 0717Python总结-return返回值,全局及局部变量,函数名的使用,函数的嵌套,nonlocal修改局部变量,及locals和globals
  18. 2020Android面试题跳楼大整理,京东-字节跳动面经+个人总结+心得
  19. 未经授权,直接划扣资金!这些支付机构的用户要小心
  20. 数据可视化实验一之单变量数据的统计图表可视化

热门文章

  1. 【MATLAB】线性代数矩阵基本运算(转置,乘法,求逆)
  2. HOT78-跳跃游戏
  3. undefined reference to imread()
  4. 上海电信SDN千兆 烽火通信光猫HG7143D
  5. chrome控制台酷炫主题
  6. 前端基础01 html标签总结
  7. Compute Shader 语法及函数 Reference for HLSL
  8. jquery class选择器失效
  9. 最简单的slob实现
  10. 使从铃声管理(RingtoneManage)获取到的Ringtone重复播放