简介
开发一个android项目流程,编写xml布局,处理所对应的Activity的界面,运行项目,这些常规操作,我们再也熟悉不过,但是ide所在底层实现java源码->….->APK生成,这些究竟是怎么产生的?是时候探究一番了。
class文件结构深入解析
什么是class文件?
class文件全名称为Java class文件,主要在平台无关性和网络移动性方面使Java更适合网络。它在平台无关性方面的任务是:为Java程序提供独立于底层主机平台的二进制形式的服务。以及能被java虚拟机(jvm)所识别的二进制文件。
这是通过百科所给出的解释,所给出的解释无非就是把java源码编译成jvm能识别的二进制文件。那我们如何去生成这个class文件呢?
- 首先必须搭建java的运行环境(jdk)。
- 配置环境变量。
- 然后通过cmd输入java查看环境变量是否配置成功。
在我们上面配置已经成功的条件下,我们开始编写一段代码:
public class Test {
public static void main(String[] args){
System.out.println("Hello java");
}
}
这代码我们再也熟悉不过了,主程序下面打印一个Hell java。接下来我们打开cmd,通过javac Test.java命令来生成Test.class文件。当怀着好奇心用文本编译器打开Test.class文件后,哇靠!这都是写什么鬼,全部都是人类看不懂的乱码。当然对于我们程序猿来说,简直就是无稽之谈了。通过各种某度,某歌搜索.class查看器,终于发现一款神器(010Editor)二进制查看器。然后用这个神器打开.class文件可查看到:
啰嗦了这么多废话,依旧懵逼看着这一大串二进制数字,继续搜索资料。n久过后,先来一张图片来了解一下class的文件结构:
class文件类型:
U1 1个字节,无符号类型
U2 2个字节,无符号类型
U4 4个字节,无符号类型
U8 8个字节,无符号类型
class文件名称:
magic:
确定这个文件是否为一个能被虚拟机所接受的 Class 文件。魔数值固定为 CAFEBABE,不会改变。可以查看我们的Test.class文件中前4个字节,就可以确定这个是class文件。
minor_version、major_version
minor_version 和 major_version 的值分别表示 Class 文件的副、主版本。它们共同构成了 Class 文件的格式版本号,可以查看到Test.class文件中第4、5个字节是次版本号,第6、7个字节是主版本号。在这里,次版本号是0,主版本号是52,(十六进制是34)
constant_pool_count
constant_pool_count常量池计数器,constant_pool_count的值等于constant_pool表中的成员数加1。constant_pool 表的索引值只有在大于 0 且小于 constant_pool_count 时才会被认为是有效的。
constant_pool
constant_pool[ ]常量池,constant_pool 是一种表结构,它包含 Class 文件结构及其子结构中引用的所有字符串常量、类或接口名、字段名和其它常量。常量池中的每一项都具备相同的格式特征——第一个字节作为类型标记用于识别该项是哪种类型的常量,称为“tagbyte”。常量池的索引范围是 1 至 constant_pool_count−1。
access_flags
access_flags访问标志,access_flags 是一种掩码标志,用于表示某个类或者接口的访问权限及基础属性。
this_class
this_class类索引,this_class 的值必须是对 constant_pool 表中项目的一个有效索引值。constant_pool 表在这个索引处的项必须为 CONSTANT_Class_info 类型常量,表示这个 Class 文件所定义的类或接口。
interfaces_count
接口计数器,interfaces_count 的值表示当前类或接口的直接父接口数量。
interfaces
接口表,interfaces[]数组中的每个成员的值必须是一个对 constant_pool 表中项目的一个有效索引值,它的长度为 interfaces_count。每个成员 interfaces[i] 必须为 CONSTANT_Class_info 类型常量
fields_count
字段计数器,fields_count 的值表示当前 Class 文件 fields[]数组的成员个数。fields[]数组中每一项都是一个 field_info 结构(§4.5)的数据项,它用于表示该类或接口声明的类字段或者实例字段 。
注意::类字段即被声明为 static 的字段,也称为类变量或者类属性,同样,实例字段是指未被声明为static 的字段。由于《Java 虚拟机规范》中,“Variable”和“Attribute”出现频率很高且在大多数场景中具备其他含义,所以译文中统一把“Field”翻译为“字段”,即“类字段”、“实例字段”。
fields[]
字段表,fields[]数组中的每个成员都必须是一个 fields_info 结构(§4.5)的数据项,用于表示当前类或接口中某个字段的完整描述。fields[]数组描述当前类或接口
声明的所有字段,但不包括从父类或父接口继承的部分。
methods_count
方法计数器,methods_count 的值表示当前 Class 文件 methods[]数组的成员个数。Methods[]数组中每一项都是一个 method_info 结构(§4.5)的数据项。
methods[]
方法表,methods[]数组中的每个成员都必须是一个 method_info 结构(§4.6)的数据项,用于表示当前类或接口中某个方法的完整描述。如果某个 method_info 结构
的 access_flags 项既没有设置 ACC_NATIVE 标志也没有设置 ACC_ABSTRACT 标志,那么它所对应的方法体就应当可以被 Java 虚拟机直接从当前类加载,而不需要引用其它类。method_info 结构可以表示类和接口中定义的所有方法,包括实例方法、类方法、实例初始化方法方法(§2.9)和类或接口初始化方法方法(§2.9)。methods[]数组
只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法。
attributes_count
属性计数器,attributes_count 的值表示当前 Class 文件 attributes 表的成员个数。attributes 表中每一项都是一个 attribute_info 结构(§4.7)的数据项。
attributes[]
属性表,attributes 表的每个项的值必须是 attribute_info 结构(§4.7)。
参考:
http://blog.csdn.net/kittyboy0001/article/details/19198227
http://blog.csdn.net/sinat_38259539/article/details/78248454