2.4 访问控制
在常量池结束之后是2字节的访问控制
表示这个class文件是类/接口、是否被public/abstract/final修饰等.
由于这些标志都由是/否表示,因此可以用0/1表示.
访问标志为2字节,可以表示16位标志,但JVM目前只定义了8种,未定义的直接写0.
Demo1.txt中的构造方法
Demo1这个示例中,我们并没有写构造函数。
由此可见,没有定义构造函数时,会有隐式的无参构造函数
2.5 类索引、父类索引、接口索引集合
表示当前class文件所表示类的名字、父类名字、接口们的名字.
它们按照顺序依次排列,类索引和父类索引各自使用一个u2类型的无符号常量,这个常量指向CONSTANT_Class_info类型的常量,该常量的bytes字段记录了本类、父类的全限定名.
由于一个类的接口可能有好多个,因此需要用一个集合来表示接口索引,它在类索引和父类索引之后.这个集合头两个字节表示接口索引集合的长度,接下来就是接口的名字索引.
2.6 字段表的集合
2.6.1 什么是字段表集合?
用于存储本类所涉及到的成员变量,包括实例变量和类变量,但不包括方法中的局部变量。
每一个字段表只表示一个成员变量,本类中所有的成员变量构成了字段表集合。
2.6.2 字段表结构的定义
- access_flags
字段的访问标志。在Java中,每个成员变量都有一系列的修饰符,和上述class文件的访问标志的作用一样,只不过成员变量的访问标志与类的访问标志稍有区别。 - name_index
本字段名字的索引。指向一个CONSTANT_Class_info类型的常量,这里面存储了本字段的名字等信息。 - descriptor_index
描述符。用于描述本字段在Java中的数据类型等信息(下面详细介绍) - attributes_count
属性表集合的长度。 - attributes
属性表集合。到descriptor_index为止是字段表的固定信息,光有上述信息可能无法完整地描述一个字段,因此用属性表集合来存放额外的信息,比如一个字段的值。(下面会详细介绍)
2.6.3 什么是描述符?
成员变量(包括静态成员变量和实例变量) 和 方法都有各自的描述符。
对于字段而言,描述符用于描述字段的数据类型;
对于方法而言,描述符用于描述字段的数据类型、参数列表、返回值。
在描述符中,基本数据类型用大写字母表示,对象类型用“L对象类型的全限定名”表示,数组用“[数组类型的全限定名”表示。
描述方法时,将参数根据上述规则放在()中,()右侧按照上述方法放置返回值。而且,参数之间无需任何符号。
2.6.4 字段表集合的注意点
一个class文件的字段表集合中不能出现从父类/接口继承而来字段;
一个class文件的字段表集合中可能会出现程序猿没有定义的字段
如编译器会自动地在内部类的class文件的字段表集合中添加外部类对象的成员变量,供内部类访问外部类。
Java中只要两个字段名字相同就无法通过编译。但在JVM规范中,允许两个字段的名字相同但描述符不同的情况,并且认为它们是两个不同的字段。
Demo1.txt中的程序入口main方法
2.7 方法表的集合
在class文件中,所有的方法以二维表的形式存储,每张表来表示一个函数,一个类中的所有方法构成方法表的集合。
方法表的结构和字段表的结构一致,只不过访问标志和属性表集合的可选项有所不同。
方法表的属性表集合中有一张Code属性表,用于存储当前方法经编译器编译过后的字节码指令。
方法表集合的注意点
如果本class没有重写父类的方法,那么本class文件的方法表集合中是不会出现父类/父接口的方法表;
本class的方法表集合可能出现程序猿没有定义的方法
编译器在编译时会在class文件的方法表集合中加入类构造器和实例构造器。
重载一个方法需要有相同的简单名称和不同的特征签名。JVM的特征签名和Java的特征签名有所不同:
Java特征签名:方法参数在常量池中的字段符号引用的集合
JVM特征签名:方法参数+返回值