文件结构

魔数:class标识
副版本号:java主版本下的细分版本信息。运行时版本号要大于等于编译时版本号,否则会报错。
主版本号:java主版本号。运行时版本号要大于等于编译时版本号,否则会报错。
常量池计数器:存储常量池的字节长度。
常量池数据区:存储常量数据。
访问标志:存储类的访问标志,如public、private
类索引:存储类的符号索引。
父类索引:存储父类的符号索引。
接口计数器:存储接口信息数据区的字节长度。
接口信息数据区:存放接口数据。
字段计数器:存储字段信息数据区字节长度。
字段信息数据区:存储字段数据。
方法计数器:存储方法信息数据区字节长度。
方法信息数据区:存储方法数据。
属性计数器:存储属性信息数据区字节长度。
属性信息数据区:存储方法体。
class常量池如何存储数据
常量池的常量有哪些?
字面量和符号引用
常量池结构

常量池计数器是从1开始计数的,不是从0开始计数,最后一个常量池项的索引值为constant_pool_count-1(出于特殊考虑,为了表示”不引用任何一个常量池项”的目的,遂将0号索引空出来,这种情况下会将索引值设置成0)
常量池项结构

tag值和类型对应关系如下:

constant_utf8_info、constant_integer_info、constant_long_info、constant_float_info、constant_double_info都是字面量结构体,而其他的都是引用结构体。
如何存储String类型的字符串常量?

如何存储类Class引用类型

哪些类型字面量会进入到常量池中?
- final修饰时,8种基本类型
- 没有final修饰时,double、float、long
- 常量池中包含的字符串类型字面量(双引号引起来的字符串)
符号引用和直接引用
符号引用(class文件中)
在java中,一个java类将会编译成一个class文件。在编译时,java类并不知道索引用的类的实际地址(内存地址),因此只能使用符号引用来代替。
直接引用(运行时内存中)
直接引用可以是:
- 直接指向目标的指针
- 相对偏移量
- 一个能间接定位到目标的句柄
引用替换时机
- 类加载的解析阶段进行替换
- 运行期间
class中的特殊字符串
特殊字符串包括三种:类的全限定名、字段和方法的描述符,特殊方法的方法名。
类的全限定名
源文件中一个类的名字是用全限定名表述的。比如Object类,在源文件中的全限定名表示为java.lang.Object,而class文件中则是将”.”替换成”/”,也就是java/lang/Object。
描述符
- 8种基本数据类型:除了long和boolean,都是大写首字母表示,long则是J,boolean是Z
- void描述符是V。
- 对象类型:L加全限定名表示。如String的描述符为Ljava/lang/String。
- 数组类型:每增加一个维度则在对应的字段描述符前增加一个[。如String[][]的描述符为[[Ljava/lang/String。
字段描述符
字段描述符就是字段类型对应的字符或字符串。如int i的描述符就是I,String o的描述符就是Ljava/lang/Object
方法描述符
方法描述符包括所有参数的类型列表和方法返回值。格式如下:
(参数1类型 参数2类型 参数3类型 …)返回值类型。如int getSize()的描述符为()I,int read(byte[] b, int off, int len)的描述符为([BII)I。
特殊方法的方法名
- 类的构造方法用<init>表示
- 静态初始化方法用<clinit>表示
发表回复