Dex文件介绍

Dex文件是Dalvik的可执行文件,Dalvik是针对嵌入式设备设计的java虚拟机,所以Dex文件和Class文件的结构上有很大区别。为了更好的利用嵌入式你设备的资源,Dalvik在java程序编译后,还需要用dx工具将编译产生的数个Class文件整合成一个Dex文件。这样其中的各个类就可以共享数据,减少冗余,使文件结构更加紧凑。

一个设备在执行Dex文件之前,需要优化该Dex文件并生成对应的Odex文件,然后该Odex文件被Dalvik执行。Odex文件本质是个Dex文件,只是针对目标平台做了相关优化,包括对内部字节码进行一系列处理,主要为字节码验证,替换优化及空方法消除。

dex文件转换为java文件 可读_偏移量

Dex文件结构解析

名称

含义

header

Dex文件头部,记录Dex文件的相关属性

string_ids

字符串数据索引,记录了各个字符处在数据区的地址偏移量

type_ids

类型数据索引,记录了各个类型的字符串索引

proto_ids

原型数据索引,记录了方法声明的字符串、返回类型字符串、参数列表

field_ids

字段数据索引,记录所属类、声明类型及方法名等信息

method_ids

类方法索引,记录方法所属类名、方法声明及该方法名等信息

class_ids

类定义数据,记录了指定类各类信息,包括接口、超类、类数据偏移量等

data

数据区,保存着各个类的真实数据

link_data

连接数据区

字节码各部分数据详解

  • header
    header是Dex文件的文件头,简单的记录了Dex文件的一些基本信息,及大致数据分布。header的总长度是固定的0x70,其中每一信息项所占的内存空间也是相对固定的,这样做的好处,虚拟机在处理目标Dex文件初期,可以不考虑Dex文件的多样性,根据规定读取文件头,就可以获取Dex文件的大致信息。
    Dex文件头部信息:

字段名

偏移量

长度

描述

magic

0x0

8

“魔数”,格式如”/dex/n035/0”

Cheaksum

0x8

4

校验码

signature

0xC

20

SHA-1签名

File_size

0x20

4

Dex文件的长度

Header_size

0x24

4

文件头长度,009版本=0x5C,035版本=0x70

Endian_tag

0x28

4

标示字节顺序的常量

Link_size

0x2C

4

链接桥的大小,若0则为静态链接

Link_off

0x30

4

链接段的开始位置

Map_off

0x34

4

Map数据基址

String_ids_size

0x38

4

字符串列表中的字符串个数

String_ids_off

0x3C

4

字符串列表基址

Type_ids_size

0x40

4

类列表里的类型个数

Type_ids_off

0x44

4

类列表基址

Proto_ids_size

0x48

4

原型列表里的原型个数

Proto_ids_off

0x4C

4

原型列表里的字段个数

Field_ids_size

0x50

4

字段列表里的字段个数

Field_ids_off

0x54

4

字段列表的基址

Method_ids_size

0x58

4

方法列表里的方法个数

Method_ids_off

0x5C

4

方法列表基址

Class_ids_size

0x60

4

类定义表中的类的个数

Class_ids_off

0x64

4

类定义表基址

Data_ids_size

0x68

4

数据段大小,必须以4字节对其

Data_ids_off

0x6C

4

数据段基址

源码位于 /dalvik/libdex/DexFile.h:DexHeader

dex文件转换为java文件 可读_数据_02


  • string_ids
    这一区域存储的是Dex文件字符串资源的索引信息,该索引信息是目标字符串在Dex文件数据区所在的真实物理偏移量。

源码位于/dalvik/libdex/DexFile.h:DexStringId

dex文件转换为java文件 可读_数据_03

stringDataOff记录了目标字符串在Dex文件中的实际偏移量,虚拟机想读取该字符串时,只需将Dex文件在内存中的起始地址加上stringDataOff所指的偏移量,就是该字符串在内存中的实际物理地址。
在Dex文件中,每个每个字符串对应一个DexStringId,大小4B。另外虚拟机通过DexHeader中的String_ids_size获得当前Dex文件中的字符串的总数,通过乘法就可对该索引资源进行访问。

未完待续