Dex结构图:
DexHeader:
checksum 是对去除 magic 、 checksum 以外的文件部分作 alder32 算法得到的校验值,用于判断 DEX 文件是否被篡改。
signature 是对除去 magic 、 checksum 、 signature 以外的文件部分作 sha1 得到的文件哈希值。
示例代码:
public class HelloWorld {
int a = 0;
static String b = "HelloDalvik";
public int getNumber(int i, int j) {
int e = 3;
return e + i + j;
}
public static void main(String[] args) {
int c = 1;
int d = 2;
HelloWorld helloWorld = new HelloWorld();
String sayNumber = String.valueOf(helloWorld.getNumber(c, d));
System.out.println("HelloDex!" + sayNumber);
}
}
DexStringId:
struct DexStringId {
u4 stringDataOff;
};
string_ids 是一个偏移量数组,stringDataOff 表示每个字符串在 data 区的偏移量。根据偏移量在 data 区拿到的数据中.
DexTypeId:
struct DexTypeId{
u4 descriptorIdx; /*指向DexStringId列表的索引*/
}
DexProtoId:
struct DexProtoId{
u4 shortyIdx; /*指向DexStringId列表的索引*/
u4 returnTypeIdx; /*指向DexTypeId列表的索引*/
u4 parametersOff; /*指向DexTypeList的位置偏移*/
}
struct DexTypeList{
u4 size; /*DexTypeItem的个数*/
DexTypeItem list[1]; /*DexTypeItem结构*/
}
struct DexTypeItem{
u2 typeIdx; /*指向DexTypeId列表的索引*/
}
DexFieldId:
struct DexFieldId{
u2 classIdx; /*类的类型,指向DexTypeId列表的索引*/
u2 typeIdx; /*字段类型,指向DexTypeId列表的索引*/
u4 nameIdx; /*字段名,指向DexStringId列表的索引*/
}
注意不包括static属性。
〇int HelloWorld.a , ①java.lang.String HelloWorld.b ,②java.io.PrintStream java.lang.System.out
DexMethodId:
struct DexMethodId{
u2 classIdx; /*类的类型,指向DexTypeId列表的索引*/
u2 protoIdx; /*声明类型,指向DexProtoId列表的索引*/
u4 nameIdx; /*方法名,指向DexStringId列表的索引*/
}
注意也不包括static属性。
DexClassDef:
struct DexClassDef{
u4 classIdx; /*类的类型,指向DexTypeId列表的索引*/
u4 accessFlags; /*访问标志*/
u4 superclassIdx; /*父类类型,指向DexTypeId列表的索引*/
u4 interfacesOff; /*接口,指向DexTypeList的偏移*/
u4 sourceFileIdx; /*源文件名,指向DexStringId列表的索引*/
u4 annotationsOff; /*注解,指向DexAnnotationsDirectoryItem结构*/
u4 classDataOff; /*指向DexClassData结构的偏移*/
u4 staticValuesOff; /*指向DexEncodedArray结构的偏移*/
}
struct DexClassData{
DexClassDataHeader header; /*指定字段与方法的个数*/
DexField* staticFields; /*静态字段,DexField结构*/
DexField* instanceFields; /*实例字段,DexField结构*/
DexMethod* directMethods; /*直接方法,DexMethod结构*/
DexMethod* virtualMethods; /*虚方法,DexMethod结构*/
}
struct DexClassDataHeader{
u4 staticFieldsSize; /*静态字段个数*/
u4 instanceFieldsSize; /*实例字段个数*/
u4 directMethodsSize; /*直接方法个数*/
u4 virtualMethodsSize; /*虚方法个数*/
}
struct DexField{
uleb128 fieldIdx; /*指向DexFieldId的索引*/
uleb128 accessFlags; /*访问标志*/
}
struct DexMethod{
uleb128 methodIdx; /*指向DexMethodId的索引*/
uleb128 accessFlags; /*访问标志*/
uleb128 codeOff; /*指向DexCode结构的偏移*/
}
struct DexCode {
u2 registersSize; /* 使用的寄存器个数 */
u2 insSize; /* 参数个数 */
u2 outsSize; /* 调用其他方法时使用的寄存器个数 */
u2 triesSize; /* Try/Catch个数 */
u4 debugInfoOff; /* 指向调试信息的偏移 */
u4 insnsSize; /* 指令集个数,以2字节为单位 */
u2 insns[insnsSize]; /* 指令集 */
};
accessFlags: ACC_PUBLIC,ACC_STATIC,ACC_,ACC_CONSTRUCTOR
staticFields: static java.lang.String HelloWorld.b
instanceFields: int HelloWorld.a
directMethods: void HelloWorld.<clinit>(),void HelloWorld.<init>(),void HelloWorld.main(java.lang.String[])
virtualMethods: int HelloWorld.getNumber(int, int)
DexMapList:
struct DexMapList {
u4 size; /* 条目个数 */
DexMapItem list[size]; /* 条目列表 */
};
struct DexMapItem {
u2 type; /* 结构类型,kDexType 开头 */
u2 unused; /* 未使用,用于字节对齐 */
u4 size; /* 连续存放的结构个数 */
u4 offset; /* 结构的偏移 */
};
/* 结构类型代码 */
enum {
kDexTypeHeaderItem = 0x0000,
kDexTypeStringIdItem = 0x0001,
kDexTypeTypeIdItem = 0x0002,
kDexTypeProtoIdItem = 0x0003,
kDexTypeFieldIdItem = 0x0004,
kDexTypeMethodIdItem = 0x0005,
kDexTypeClassDefItem = 0x0006,
kDexTypeMapList = 0x1000,
kDexTypeTypeList = 0x1001,
kDexTypeAnnotationSetRefList = 0x1002,
kDexTypeAnnotationSetItem = 0x1003,
kDexTypeClassDataItem = 0x2000,
kDexTypeCodeItem = 0x2001,
kDexTypeStringDataItem = 0x2002,
kDexTypeDebugInfoItem = 0x2003,
kDexTypeAnnotationItem = 0x2004,
kDexTypeEncodedArrayItem = 0x2005,
kDexTypeAnnotationsDirectoryItem = 0x2006,
};
总结图: