JVM类加载·一 Class类文件

2021-08-08

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。

 

 

二、 字节码和数据类型