深入理解JVM读书笔记--Class文件结构

时间:2023-02-15 11:45:06

一.Class文件结构

1. Class文件是一组以8位字节为基础的二进制流,采用一种类似C语言结构体的伪代码类存储。它只有两种数据类型:无符号数和表。

2. 无符号数属于基本的数据类型,以u1u2u4u8分表代表1个,2个,4个,8个字节。他可以用来描述数字,索引引用,数量值,UTF-8编码的字符串。

3. 表有多个无符号数或其他表作为数据项构成的符合数据类型,所有的表都已_info结尾。

4. Class文件格式

类型

名称

数量

U4

Magic(魔数)

1

U2

Minor_version(次版本号)

1

U2

Major_version(主版本号)

1

U2

Constant_pool_length

1

Cp_info

Constant_pool(常量池)

Constant_pool_length-1

U2

Access_flags

1

U2

This_class

1

U2

Super_class

1

U2

Interfaces_count

1

U2

Interfaces

Interfaces_count

U2

Fields_count

1

Field_info

fields

Fields_count

U2

Methods_count

1

Method_info

methods

Methods_count

U2

Attributes_count

1

Attribute_info

attributes

Attribute_count

5. 魔数和class文件的版本

a) 魔数:确定这个文件是否为一个能被虚拟机接受的class文件。

b) 版本号:每个JDK版本对应一个版本号段,低版本的JDK不能执行标识高版本JDK的版本号class文件,但是高版本的可以执行低版本的(向下兼容的特性)。

c) 常量池:(注意常量池使用1计数的,0表示常量池为空)常量池主要存放两类常量:字面量(Literal)和符号引用(Symbolic Reference)。

字面量包括文本字符串,被声明为final的常量等。

符号引用包括:类和接口的全限定名;字段名称和描述符;方法的名称和描述符。

常量池中的每一项都是一个表。

类型

标志

描述

CONSTANT_UTF-8_info

1

UTF-8编码的字符串

CONSTANT_Integer_info

3

整形字面量

CONSTANT_Float_info

4

浮点型字面量

CONSTANT_Long_info

5

长整型字面量

CONSTANT_Double_info

6

双精度浮点型字面量

CONSTANT_Class_info

7

类或接口的符号引用

CONSTANT_String_info

8

字符串类型字面量

CONSTANT_Fieldref_info

9

字段的符号引用

CONSTANT_Methodref_info

10

类中方法的引用

CONSTANT_InterfaceMethodref_info

11

接口中方法的引用

CONSTANT_NameAnd_info

12

字段或方法的部分符号引用

d) 访问标志:用于标识一些类或借口层次的访问信息,包括:这个class是接口还是类,是否定义为public类型等

标志名称

标志值

含义

ACC_PUBLIC 

0x0001

是否为public类型

ACC_FINAL

0x0010

是否声明为final,只有类可以设置

ACC_SUPER

0x0020

是否允许使用invokespcial字节码指令

ACCC_INTERFACE

0x0200

标识这是一个接口

ACC_ABSTRACT

0x0400

是否为abstract类型,对于接口和类这个标识为真,其他类为假

ACC_AYNTHETIC

0x1000

标识这个类并非由用户代码产生

ACC_ANNOTATION

0x2000

标识这是一个注解

ACC_ENUM

0x4000

标识这是一个枚举

6. 类索引、父类索引和接口索引集合:类索引,父类索引都是一个u2类型的数据,但是接口索引集合是一组u2类型的集合,class文件由这三项确定继承关系。

7. 字段表集合:用于描述接口或类中声明的变量。字段包括类变量和实例变量,但是不包括方法内的变量。

a) 字段访问标识

标识名称

标志值

ACC_PUBLIC 

0x0001

ACC_PRIVATE

0x0002

ACC_PROTECTED

0x0004

ACC_STATIC

0x0008

ACC_FINAL

0x0010

ACC_VOLTATILE

0x0040

ACC_TRANSIENT

0x0080

ACC_SYNTHETIC

0x1000

ACC_ENUM

0x4000

 

8. 方法表集合:类似字段表集合。

a) 访问标志

标识名称

标志值

ACC_PUBLIC 

0x0001

ACC_PRIVATE

0x0002

ACC_PROTECTED

0x0004

ACC_STATIC

0x0008

ACC_FINAL

0x0010

ACC_SYNCHRONIZED

 

ACC_BRIDGE

0x0040

ACC_VARARGS

0x0080

ACC_NATIVE

0x0100

ACC_ABSTRACT

0x0400

ACC_STRICT

0x0800

ACC_SYNTHETIC

0x1000

b)  方法的重载(overload)和重写(override

重载:除了要与原来的方法具备相同的名称之外,还要具备不同的特征签名,特征签名就是一个方法中各个参数在常量池中的字段符号引用的集合。(java代码的方法特征签名只包括了方法名称,参数顺序,即参数类型,而字节码的特征签名还包括方法返回值及受检异常表)。

重写: 拥有相同的方法名和特征签名但有不同的方法体。

9. 属性集合:在class文件,字段表,方法表中都可以携带自己的属性表集合,以用于描述某些场景专有的信息。

a) 属性表

属性名称

使用位置

含义

Code

方法表

Java代码编译成字节码指令

ConstantValue

字段表

Final关键字定义的常量值

Deprecated

类、方法表、字段表

被声明为deprecated的方法和字段

Exceptions

方法表

方法抛出异常

InnerClass

类文件

内部类列表

LineNumberTable

Code属性

Java源码的行号与字节码指令的对应关系

LocalVariableTable

Code属性

方法的局部变量描述

SourceFile

类文件

源文件名称

Synthetic

类、方法表、字段表

标识方法或字段为编译器自动生成

 

b) Javac在编译的时候会把对this关键字的访问转变为一个普通方法参数的访问,然后在虚拟机调用实例方法时自动传入此参数即可。

c) Java异常实际上是java代码的一部分不是简单地跳转。