一. class文件结构深入解析(生成&执行&内部结构)
1. 如何生成一个class文件?
class文件是能够被JVM识别,加载并执行的文件格式。说白了,它就是一种文件格式,就像mp4、jpg、txt等文件格式一样。
只有java源代码能编译成class文件吗?
下图几种语言也能编译成class文件。
2. 如何生成一个class文件?
一般来说,有两种方式生成class文件:
- IDE会自动帮我们build出class文件
- 手动通过javac去生成class文件(IDE也是通过javac生成的)
3. class文件的作用
记录一个类文件的所有信息。
4. class文件格式详解(重点)
- 一种8位字节的二进制流文件(与音视频文件一样)
- 各个数据按顺序紧密的排列,无间隙(不像有些文件,为了读取上的方便,会做一些填充,比如每80字节是一行)
- 每个类、枚举、接口都单独占据一个class文件
下面我们来讲解一下class文件结构
我们逐行来讲解每个字段的作用。
- magic字段。它是无符号4字节类型。它的作用是一个摘要段,好比文件的md5加密,用来判断class文件是否有被篡改。
- minor_version字段。它指明class文件最早可以支持的jdk版本。
- major_version字段。表示当前class文件是由那个jdk版本生成的。
- constant_pool_count字段。表示class文件中常量池的数量,通常来说,只有一个常量池。
constant_pool字段[核心]。这个字段代表真正的常量池,它是cp_info类型。也就是说,是一个结构体类型。constant_pool的取值范围如下:
CONSTANT_Integer_info:int类型
CONSTANT_Long_info:long类型
CONSTANT_String_info:String类型
CONSTANT_Class_info:类相关信息
CONSTANT_Fieldref_info:类中成员变量相关信息
CONSTANT_Methodref_info:类中方法相关信息access_flag字段。表示class文件的作用域,比如public,private等。如下图,access_flags可以取如下值。
- this_class字段。在java源文件中没有定义this关键字,而jdk在生成class文件时补充了这个字段。
- super_class字段。跟this_class原理类似。
- interfaces_count字段。表明当前class文件实现了多少个接口,且只会记录直接实现的接口数量。
- interfaces字段。表明当前class文件直接实现的接口数量。
- fields_count字段。表明当前class文件所有成员变量个数。
- fields字段。是field_info类型。表明成员变量类型、名称等。记录当前class文件所有成员变量。
- methods_count字段。
- methods字段。
- attribute_count字段。属性个数。
- attributes字段。
5. class文件弊端
- 内存占用大,不适合移动端
- 堆栈的加栈模式,加载速度慢
- 文件IO操作多,类查找慢
二. dex文件结构深入解析(生成&执行&内部结构)
1. 什么是dex文件?
能够被DVM识别,加载并执行的文件格式
2. 如何生成一个dex文件?
- 通过IDE自动build生成
- 手动通过dx命令生成dex文件
那么,如何用dx命令生成dex文件,并在手机上运行呢?
- 找到 sdk目录/build-tools/sdk版本,如我的路径:
/Users/colinambitious/Library/Android/sdk/build-tools/26.0.22.
在此文件夹下可以找到dx文件,将此目录设为环境变量。 写一个Test.java文件
public class Test{ public static void main(String args[]){ System.out.println("Hello World."); } }
使用以下命令,编译成class文件:
javac -target 1.6 -source 1.6 Test.java- 使用adb命令,将生成的class文件push到手机上
adb push Test.dex /storage/emulated/0 - 使用adb shell命令,远程连接到手机
adb shell - 运行该dex文件
dalvikvm -cp ./Test.dex Test
3. dex文件的作用
记录整个工程中所有类文件的信息,
4. dex文件格式详解(重点)
- 一种8字节的二进制流文件
- 各个数据按顺序紧密排列,无间隙
- 整个应用所有java源文件都在一个dex中
我们来结合下面这张图来讲解。
dex文件总共有三个部分:文件头、索引区、数据区。
- 文件头header。主要记录了dex文件信息。
- 索引区。包含了字符串索引、类型索引、方法原型索引、域索引、方法索引。
- 数据区。包含了索引区索引的内容。
三. class文件与dex文件对比
- 本质上class文件和dex文件都是一样的(java源文件演变而来),而dex文件又是从class文件演变而来的。
- class文件存在许多冗余信息,dex去除冗余。因为,class文件一个类就有一个常量池,dex文件中所有数据都是存储在同一个数据区的。
从下面这张图可以看出,jar包中每一个class都有header、constant pool等,而dex把这些所有class的信息整合到了一起。