共计 2070 个字符,预计需要花费 6 分钟才能阅读完成。
jvm 能够了解的代码叫做字节码(.class 文件)。java,clojure,groovy,scala,jruby 等语言的程序通过编译器编译成字节码运行在虚拟机上。
class 文件构造总结
class 文件通过 classfile 定义,相似 c 语言构造体,记录了诸如以后类、父类、接口、字段属性、办法等信息。
ClassFile {
u4 magic; //Class 文件的标记
u2 minor_version;//Class 的小版本号
u2 major_version;//Class 的大版本号
u2 constant_pool_count;// 常量池的数量
cp_info constant_pool[constant_pool_count-1];// 常量池
u2 access_flags;//Class 的拜访标记
u2 this_class;// 以后类
u2 super_class;// 父类
u2 interfaces_count;// 接口
u2 interfaces[interfaces_count];// 一个类能够实现多个接口
u2 fields_count;//Class 文件的字段属性
field_info fields[fields_count];// 一个类会能够有多个字段
u2 methods_count;//Class 文件的办法数量
method_info methods[methods_count];// 一个类能够有个多个办法
u2 attributes_count;// 此类的属性表中的属性数
attribute_info attributes[attributes_count];// 属性表汇合
}
magic
每个 Class 文件的头 4 个字节称为魔数(Magic Number), 它的惟一作用是确定这个文件是否为一个能被虚拟机接管的 Class 文件。
版本号
紧接着魔数的四个字节存储的是 Class 文件的版本号:第 5 和第 6 位是次版本号,第 7 和第 8 位是主版本号。
每当 Java 公布大版本(比方 Java 8,Java9)的时候,主版本号都会加 1。你能够应用 javap -v 命令来疾速查看 Class 文件的版本号信息。
高版本的 Java 虚拟机能够执行低版本编译器生成的 Class 文件,然而低版本的 Java 虚拟机不能执行高版本编译器生成的 Class 文件。所以,咱们在理论开发的时候要确保开发的的 JDK 版本和生产环境的 JDK 版本保持一致。
常量池
字面量:文本字符串、申明为 final 的常量
符号援用:类和接口的全限定名、字段的名称和描述符、办法的名称和描述符
拜访标记
在常量池完结之后,紧接着的两个字节代表拜访标记,这个标记用于辨认一些类或者接口档次的访问信息,包含:这个 Class 是类还是接口,是否为 public 或者 abstract 类型,如果是类的话是否申明为 final 等等。
类拜访和属性修饰符:
field
形容接口或类中申明的变量,包含类级变量以及实例变量,不包含在办法外部申明的局部变量。类变量就是有 static 修饰符的,实例变量就是没有 static 修饰符的。
字段的构造:
- access_flags: 字段的作用域(public ,private,protected 修饰符),是实例变量还是类变量(static 修饰符), 可否被序列化(transient 修饰符), 可变性(final), 可见性(volatile 修饰符,是否强制从主内存读写)。
- name_index: 对常量池的援用,示意的字段的名称;
- descriptor_index: 对常量池的援用,示意字段和办法的描述符;
- attributes_count: 一个字段还会领有一些额定的属性,attributes_count 寄存属性的个数;
- attributes[attributes_count]: 寄存具体属性具体内容。
- 上述这些信息中,各个修饰符都是布尔值,要么有某个修饰符,要么没有,很适宜应用标记位来示意。而字段叫什么名字、字段被定义为什么数据类型这些都是无奈固定的,只能援用常量池中常量来形容。
-
字段的 access_flag 的取值:
办法 method
Class 文件存储格局中对办法的形容与对字段的形容简直采纳了完全一致的形式。办法表的构造如同字段表一样,顺次包含了拜访标记、名称索引、描述符索引、属性表汇合几项。
method_info(办法表的) 构造:
办法表的 access_flag 取值:
留神:因为 volatile 修饰符和 transient 修饰符不能够润饰办法,所以办法表的拜访标记中没有这两个对应的标记,然而减少了 synchronized、native、abstract 等关键字润饰办法,所以也就多了这些关键字对应的标记。
属性
在 Class 文、字段表、办法表中都能够携带本人的属性表汇合,以用于形容某些场景专有的信息。与 Class 文件中其它的数据我的项目要求的程序、长度和内容不同,属性表汇合的限度略微宽松一些,不再要求各个属性表具备严格的程序,并且只有不与已有的属性名反复,任何人实现的编译器都能够向属性表中写入本人定义的属性信息,Java 虚拟机运行时会疏忽掉它不意识的属性。