https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html
JVM不与任何语言绑定,包括JAVA,它只认class文件这种特殊的文件格式。
class文件中包含了JAVA虚拟机指令集、符号表和其他信息。
class文件格式采用类似于C结构体的结构来存储数据,数据类型只有两种,基本的无符号类型和表(Tables)类型,表类型由0个或多个无符号类型或其他表组成。
//跟rust u8代表8位不同,这里代表的是字节。Byte。
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
u1,u2,u4,u8分别表示多少个字节数,无符号类型可以用来描述数字,索引引用等。
表这种复合结构类型通常以_info结尾。
字节间没有分隔符,跟网络编程似的,第几个字节代表什么是严格按规范来的。
一、 class文件结构解析
1.1 magic 魔数
前4各字节称为魔数 magic number,它唯一的作用就是确定这个文件是不是能被当前虚拟机接受的class文件。
1.2 minor_version & major_version
第5-6个字节 次版本号,7-8是主版本号。JAVA8-11分别对应52-55,所以17是61。
1.3 constant_poll_count 常量池计数
第 9-10个字节。这个计数是从1开始的,代表常量池中有多少个常量。
1.4 co_info
第11个字节是常量池入口,常量池是class私有的嘛,然后长度也不固定,所以需要前面那个 常量池计数。
常量池中主要有两大类常量:字面量和符号引用。
字面量比较接近Java语言层面的常量概念,如文本字符串、被声明为final的常量值等。
符号引用属于编译原理方面的概念,主要包含下面几类常量:
1. 类和接口的全限定名
2. 字段的名称和描述符
3. 方法的名称和描述符
4. 方法句柄和方法类型
5. 动态调用点和动态常量
编译.java代码到.class文件中保存不了各个方法、字段在内存中的地址信息,因为还没有被虚拟机加载。。
常量池中每一项都是一个表,类型很多。。。我觉得不重要就先不看了。。。
1.5 access_flags
常量池结束后的两个字节 代表 访问控制。值和它的意义有一个表维护。参考https://docs.oracle.com/javase/specs/jvms/se16/html/jvms-4.html#jvms-4.1-200-E.1
表示类或接口层次的访问信息,比如这个class是类还是接口;是否是public的,是否是abstract的;是不是朱姐,是不是枚举,是不是final的等等。
因为有两个字节,所以有16个标识位,但是目前只用了9个数字。
1.6 this_class类索引、super_class父类索引
这俩都是2个字节的数据。
类索引用来确定这个类的全限定名,父类索引用来确定这个类的父类的全限定名。因为JAVA不允许多继承,所以只有一个父类索引。
但是java.lang.Object没有父类,所以它的父类索引是0。
二、 字节码和数据类型