您的位置:首页 > 移动开发 > Android开发

android中class文件与dex文件解析(一)

2018-03-02 10:09 1041 查看

简介

每次编写玩java或者android代码,运行ide中的run,编译器会自动生成出.class文件,.dex文件,已经android应用的APK文件,但并不清楚生成的流程,已经这些文件生成二进制的格式,接下来一探究竟。

目录

class文件结构深入解析

dex文件结构深入解析

class文件结构深入解析

什么是class文件

class文件全名称为Java class文件,主要在平台无关性和网络移动性方面使Java更适合网络。它在平台无关性方面的任务是:为Java程序提供独立于底层主机平台的二进制形式的服务。以及能被java虚拟机所识别的二进制文件。

如何生成一个class文件

1.  通过IDE自动帮我们build
2.  手动通过javac去生成class文件


下面首先给出一段简单的Java程序,以这段代码编译成的Class文件为基础进行Class文件结构的介绍,代码如下:

public class hello {

public static void main(String[] args){

System.out.println("hello word");

}


然后我们打开cmd,利用javac hello.java命令生成hello.class文件。然后我们可以用010Editer打开.class二进制文件进行查看:



1. magic魔数,魔数的唯一作用是确定这个文件是否为一个能被虚拟机所接受的 Class 文件。魔数值固定为 0xCAFEBABE,不会改变。



2. minor_version、major_version副版本号和主版本号,minor_version 和 major_version 的值分别表示 Class 文件的副、主版本。它们共同构成了 Class 文件的格式版本号。譬如某个 Class 文件的主版本号为 M,副版本号为 m,那么这个 Class 文件的格式版本号就确定为 M.m。Class 文件格式版本号大小的顺序为:1.5 < 2.0 < 2.1。



3. constant_pool_count常量池计数器,constant_pool_count的值等于constant_pool表中的成员数加1。constant_pool 表的索引值只有在大于 0 且小于 constant_pool_count 时才会被认为是有效的。

#define CONSTANT_Utf8                       1 //UTF-8编码的Unicode字符串
#define CONSTANT_Integer                    3 //int类型的字面值
#define CONSTANT_Float                      4 //float类型的字面值
#define CONSTANT_Long                       5 //long类型的字面值
#define CONSTANT_Double                     6 //double类型的字面值
#define CONSTANT_Class                      7 //对一个类或接口的符号引用
#define CONSTANT_String                     8 //String类型字面值的引用
#define CONSTANT_Fieldref                   9 //对一个字段的符号引用
#define CONSTANT_Methodref                  10 //对一个类中方法的符号引用
#define CONSTANT_InterfaceMethodref         11 //对一个接口中方法的符号引用
#define CONSTANT_NameAndType                12 //对一个字段或方法的部分符号引用


4.constant_pool[ ]常量池,constant_pool 是一种表结构,它包含 Class 文件结构及其子结构中引用的所有字符串常量、类或接口名、字段名和其它常量。常量池中的每一项都具备相同的格式特征——第一个字节作为类型标记用于识别该项是哪种类型的常量,称为“tagbyte”。常量池的索引范围是 1 至 constant_pool_count−1。

5. access_flags访问标志,access_flags 是一种掩码标志,用于表示某个类或者接口的访问权限及基础属性。

6. this_class类索引,this_class 的值必须是对 constant_pool 表中项目的一个有效索引值。constant_pool 表在这个索引处的项必须为 CONSTANT_Class_info 类型常量,表示这个 Class 文件所定义的类或接口。

7. interfaces_count接口计数器,interfaces_count 的值表示当前类或接口的直接父接口数量。

interfaces[]接口表,interfaces[]数组中的每个成员的值必须是一个对 constant_pool 表中项目的一个有效索引值,它的长度为 interfaces_count。每个成员 interfaces[i] 必须为 CONSTANT_Class_info 类型常量(§4.4.1),其中 0 ≤ i interfaces_count。在 interfaces[]数组中,成员所表示的接口顺序和对应的源代码中给定的接口顺序(从左至右)一样,即 interfaces[0]对应的是源代码中最左边的接口。

8.fields_count字段计数器,fields_count 的值表示当前 Class 文件 fields[]数组的成员个数。fields[]数组中每一项都是一个 field_info 结构(§4.5)的数据项,它用于表示该类或接口声明的类字段或者实例字段 。

注意::类字段即被声明为 static 的字段,也称为类变量或者类属性,同样,实例字段是指未被声明为static 的字段。由于《Java 虚拟机规范》中,“Variable”和“Attribute”出现频率很高且在大多数场景中具备其他含义,所以译文中统一把“Field”翻译为“字段”,即“类字段”、“实例字段”。

9.fields[]

字段表,fields[]数组中的每个成员都必须是一个 fields_info 结构(§4.5)的数据项,用于表示当前类或接口中某个字段的完整描述。fields[]数组描述当前类或接口

声明的所有字段,但不包括从父类或父接口继承的部分。

10.methods_count

方法计数器,methods_count 的值表示当前 Class 文件 methods[]数组的成员个数。Methods[]数组中每一项都是一个 method_info 结构(§4.5)的数据项。

11.methods[]

方法表,methods[]数组中的每个成员都必须是一个 method_info 结构(§4.6)的数据项,用于表示当前类或接口中某个方法的完整描述。如果某个 method_info 结构的 access_flags 项既没有设置 ACC_NATIVE 标志也没有设置 ACC_ABSTRACT 标志,那么它所对应的方法体就应当可以被 Java 虚拟机直接从当前类加载,而不需要引用其它类。method_info 结构可以表示类和接口中定义的所有方法,包括实例方法、类方法、实例初始化方法方法(§2.9)和类或接口初始化方法方法(§2.9)。methods[]数组只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法。

12.attributes_count

属性计数器,attributes_count 的值表示当前 Class 文件 attributes 表的成员个数。attributes 表中每一项都是一个 attribute_info 结构(§4.7)的数据项。

13.attributes[]

属性表,attributes 表的每个项的值必须是 attribute_info 结构(§4.7)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: