编辑
2024-08-01
后端
00
请注意,本文编写于 282 天前,最后修改于 281 天前,其中某些信息可能已经过时。

目录

常量池的作用
常量池的解析
1. CONSTANTClassinfo
2. CONSTANTFieldrefinfo
3. CONSTANTMethodrefinfo
4. CONSTANTInterfaceMethodrefinfo
5. CONSTANTStringinfo
6. CONSTANTIntegerinfo
7. CONSTANTFloatinfo
8. CONSTANTLonginfo
9. CONSTANTDoubleinfo
10. CONSTANTNameAndTypeinfo
11. CONSTANTUtf8info
12. CONSTANTMethodHandleinfo
13. CONSTANTMethodTypeinfo
14. CONSTANTDynamicinfo
15. CONSTANTInvokeDynamicinfo
16. CONSTANTModuleinfo
17. CONSTANTPackageinfo

总结一下最近看的书中的知识点,以后多翻阅,都是很底层的概念

Java虚拟机规范定义了Java字节码的格式和行为,其中包括类文件结构。类文件结构中有一个重要的部分是常量池(Constant Pool),它包含了类文件中使用的所有常量信息。常量池中有多种类型的常量项,每种常量项都有其特定的结构。

先总结一下class文件解析到内存的结构,

go
ClassFile { u4 magic; // 魔数,用于标识文件格式,固定为0xCAFEBABE。 u2 minor_version; // 类文件的次版本号,与major_version一起决定了该类文件的JVM版本要求。 u2 major_version; // 类文件的主版本号。比如52表示Java SE 8,53表示Java SE 9。 u2 constant_pool_count; // 常量池中的项数加1。实际项数是constant_pool_count - 1。 cp_info constant_pool[constant_pool_count - 1]; // 常量池数组,存储类文件中用到的各种常量,如类名、方法名、字符串、数字等。 u2 access_flags; // 类访问标志,用于标识类或接口的访问属性,如public、final、super、interface、abstract等。 u2 this_class; // 指向constant_pool中的索引,表示当前类的符号引用,通常是一个CONSTANT_Class_info项。 u2 super_class; // 指向constant_pool中的索引,表示当前类的父类的符号引用。如果当前类是Object类,没有父类,这个值为0。 u2 interfaces_count; // 实现的接口数。 u2 interfaces[interfaces_count]; // 实现接口的列表,每个接口都是一个对constant_pool中CONSTANT_Class_info项的索引。 u2 fields_count; // 字段数量,即类或接口中声明的字段数(不包括从父类继承的字段)。 field_info fields[fields_count]; // 字段信息的数组,每个field_info项表示一个字段的定义,如字段的名称、类型、修饰符、属性等。 u2 methods_count; // 方法数量,即类或接口中声明的方法数(不包括从父类继承的方法)。 method_info methods[methods_count]; // 方法信息的数组,每个method_info项表示一个方法的定义,如方法的名称、描述符、修饰符、属性(包括字节码)等。 u2 attributes_count; // 类的附加属性数量。 attribute_info attributes[attributes_count]; // 类文件级别的附加属性数组,比如"SourceFile"、"InnerClasses"、"EnclosingMethod"等。 }

constant_pool_count 是一个无符号的短整型(u2),表示常量池中常量项的数量。常量池的索引是从1开始的,因此 constant_pool_count 的值比常量池中实际的常量项数量多1。如果 constant_pool_count 的值是20,那么常量池中有19个常量项。

常量项的通用结构如下

cp_info { u1 tag; u1 info[]; }
  • tag:标识常量项的类型,不同的常量项类型有不同的 tag 值。

  • info:根据 tag 值的不同,info 数组的内容也会有所不同。

常量池的作用

  • 符号引用:常量池主要用于存储类、接口、字段和方法的符号引用。这些符号引用在类加载过程中会被解析为直接引用。

  • 字面量:常量池还存储了字符串字面量、整数和浮点数常量等。

  • 运行时常量池:在类加载过程中,Java虚拟机会将常量池中的内容加载到方法区中的运行时常量池,供程序运行时使用。

常量池的解析

在类加载的解析阶段,Java虚拟机会将常量池中的符号引用替换为直接引用。这个过程包括:

  • 类或接口的解析:将类或接口的符号引用解析为指向方法区中该类或接口的直接引用。

  • 字段解析:将字段的符号引用解析为指向具体存储位置的直接引用。

  • 方法解析:将方法的符号引用解析为指向方法代码起始位置的直接引用。

以下是17种常量项的详细结构

1. CONSTANT_Class_info

java
CONSTANT_Class_info { u1 tag; // 值为7 u2 name_index; // 指向常量池中 CONSTANT_Utf8_info 的索引 }

2. CONSTANT_Fieldref_info

java
CONSTANT_Fieldref_info { u1 tag; // 值为9 u2 class_index; // 指向常量池中 CONSTANT_Class_info 的索引 u2 name_and_type_index; // 指向常量池中 CONSTANT_NameAndType_info 的索引 }

3. CONSTANT_Methodref_info

java
CONSTANT_Methodref_info { u1 tag; // 值为10 u2 class_index; // 指向常量池中 CONSTANT_Class_info 的索引 u2 name_and_type_index; // 指向常量池中 CONSTANT_NameAndType_info 的索引 }

4. CONSTANT_InterfaceMethodref_info

java
CONSTANT_InterfaceMethodref_info { u1 tag; // 值为11 u2 class_index; // 指向常量池中 CONSTANT_Class_info 的索引 u2 name_and_type_index; // 指向常量池中 CONSTANT_NameAndType_info 的索引 }

5. CONSTANT_String_info

java
CONSTANT_String_info { u1 tag; // 值为8 u2 string_index; // 指向常量池中 CONSTANT_Utf8_info 的索引 }

6. CONSTANT_Integer_info

java
CONSTANT_Integer_info { u1 tag; // 值为3 u4 bytes; // 整数值 }

7. CONSTANT_Float_info

java
CONSTANT_Float_info { u1 tag; // 值为4 u4 bytes; // 浮点数值 }

8. CONSTANT_Long_info

java
CONSTANT_Long_info { u1 tag; // 值为5 u4 high_bytes; // 高32位 u4 low_bytes; // 低32位 }

9. CONSTANT_Double_info

java
CONSTANT_Double_info { u1 tag; // 值为6 u4 high_bytes; // 高32位 u4 low_bytes; // 低32位 }

10. CONSTANT_NameAndType_info

java
CONSTANT_NameAndType_info { u1 tag; // 值为12 u2 name_index; // 指向常量池中 CONSTANT_Utf8_info 的索引 u2 descriptor_index; // 指向常量池中 CONSTANT_Utf8_info 的索引 }

11. CONSTANT_Utf8_info

java
CONSTANT_Utf8_info { u1 tag; // 值为1 u2 length; // UTF-8编码的字符串长度 u1 bytes[length]; // UTF-8编码的字符串 }

12. CONSTANT_MethodHandle_info

java
CONSTANT_MethodHandle_info { u1 tag; // 值为15 u1 reference_kind; // 引用类型,值在1到9之间 u2 reference_index; // 指向常量池中相应的索引 }

13. CONSTANT_MethodType_info

java
CONSTANT_MethodType_info { u1 tag; // 值为16 u2 descriptor_index; // 指向常量池中 CONSTANT_Utf8_info 的索引 }

14. CONSTANT_Dynamic_info

java
CONSTANT_Dynamic_info { u1 tag; // 值为17 u2 bootstrap_method_attr_index; // 指向BootstrapMethods属性的索引 u2 name_and_type_index; // 指向常量池中 CONSTANT_NameAndType_info 的索引 }

15. CONSTANT_InvokeDynamic_info

java
CONSTANT_InvokeDynamic_info { u1 tag; // 值为18 u2 bootstrap_method_attr_index; // 指向BootstrapMethods属性的索引 u2 name_and_type_index; // 指向常量池中 CONSTANT_NameAndType_info 的索引 }

16. CONSTANT_Module_info

java
CONSTANT_Module_info { u1 tag; // 值为19 u2 name_index; // 指向常量池中 CONSTANT_Utf8_info 的索引 }

17. CONSTANT_Package_info

java
CONSTANT_Package_info { u1 tag; // 值为20 u2 name_index; // 指向常量池中 CONSTANT_Utf8_info 的索引 }

这些结构定义了常量池中每个常量项的格式,使得Java虚拟机能够正确解析和使用这些常量。每个常量项都有一个唯一的 tag 值,用于标识其类型,并跟随相应的数据结构。

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!