Class文件 vs Dex文件 你应该知道的东西

·  阅读 915

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

Class文件的逻辑结构

image.png

文件头
类型名称数量
u4魔数1
u2次版本号1
u2主版本号1

魔数的唯一作用是告诉虚拟机,这是一个可接受的class文件,固定值为0xCAFEBABE

常量池
类型名称数量
u2常量池计数1
cp_info常量常量池计数 -1

常量池就是class文件的资源仓库,占用空间较大。

常量池容器的计数从1开始,所以常量的数量是计数-1

cp_info能容纳哪些内容

  • 字面量
    • 字符串文本
    • final常量的值
    • 基本数据类型的值
  • 符号
    • 类和接口的完全限定名
    • 字段名和类型
    • 方法名和类型

cp_info 的结构

    struct cp_info {
       u1 tag;//类型
       u1 info[]; //数据
    }
复制代码
tag表示字面量细分结构
1字符串Utf8_info
34字节数值(int)Integer_info
44字节数值(float)Float_info
58字节数值(float)Long_info
68字节数值(double)Double_info
7类和接口的完全限定名Class_info
8java.lang.String类型的常量实例String_info
9字段Fieldref_info
10方法Methodref_info
11类实现的接口InterfaceMethodref_info
12字段或方法的名称及类型NameAndType_info
15方法句柄MethodHandle_info
16方法类型MethodType_info
18动态调用InvokeDynamic_info

常量池中的字符串

    struct CONSTANT_String_info{
        u1 tag = 8; //固定取值8
        u2 string_index;//指向某个Utf8_info在常量池中的索引
    }
    struct CONSTANT_Utf8_info{
        u1 tag = 1; //固定取值1
        u2 length;//Utf8编码的字节数组的长度
        u1 bytes[length];//Utf8编码的字节数组
    }
    
复制代码
类信息
类型名称数量
u2访问修饰限定符1
u2this class1
u2super class1
u2接口计数1
u2接口接口计数
字段表
类型名称数量
u2字段表计数1
field_info字段字段表计数

字段包括类级别和实例级别的变量,不包括方法内部的局部变量。

方法表(存放方法描述)
类型名称数量
u2方法表计数1
method_info字段方法表计数
属性信息

结构

  • 属性名:属性值

dex文件

image.png

class文件和dex的区别

image.png

dex文件的文件头
    struct DexHeader{
        u1 magic[8];//魔数和版本号
        u4 checksum;//adler32算法校验码
        u1 signature[kSHA1DigestLen];//文件内容签名
        u4 fileSize;//文件总大小
        u4 headerSize;//文件头大小
        u4 endianTag;//字节序
        u4 linkSize;
        u4 linkOff;
        u4 mapOff;
    }
复制代码
dex文件的索引区
    struct DexStringId{
        u4 stringDataOff;//string_data_item的文件偏移量
    }
    struct DexTypeId{
        u4 descriptorIdx;//指向dexStringId的索引
    }
    struct DexFieldId{
        u2 classIdx;//所在类,指向dexTypeId的索引
        u2 typeIdx;//类型,指向dexTypeId的索引
        u4 nameIdx;//字段名,指向dexStringId的索引
    }
    struct DexMethodId{
        u2 classIdx;//索引到typeIds,表示所在类
        u2 protoIdx;//索引到protoIds,表示方法原型
        u4 nameIdx;//索引到stringIds,表示方法名
    }
    struct DexProtoId{
        u2 shortyIdx;//索引到stringIds,表示短描述符
        u2 returnTypeIdx;//索引到typeIds,表示返回值类型
        u4 parametersOff;//type_list中的偏移量,参数类型
    }
复制代码
索引区&数据区

image.png

class文件 vs dex文件

class文件

  • 每个类都有独立的常量池,导致代码冗余
  • 每个类属于一个文件
  • 基于栈的字节码

dex文件

  • 常量记录在数据区,所有类都通过索引获取常量的值,相同的常量可以合并,大大降低类代码的冗余。节约移动端安装包的体积。
  • 所有类在同一个文件中,即使是multdex,文件总数也远小于class文件(降低I/0操作开销)
  • 基于虚拟寄存器的字节码(节约内存)
分类:
Android
标签:
分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改