1.常量池概述
- 常量池是
Class
文件中内容最为丰富的区域。常量池对于Class
文件中字段和方法的解析有着重要的作用。 - 在版本号之后,紧跟着的就是常量池的数量以及若干个常量池表项。
- 由于常量池中的常量不是固定的,所以在设置了一个
u2
类型的无符号数,来代表常量池容量计数值(constant_pool_count
)。
- 字节码文件中的常量池分为两个部分:
a) 一个 constant_pool_count - u2
(无符号数) ,表示常量池中有多少个常量。
b) 若干个constant_pool
- 常量池表,表示常量池内容。
常量池表中,存放的是编译时期生成的字面量
和符号引用
,在运行时,这部分内容被加载进方法区的运行时常量池中存放(在JDK8
及以后,是放在了元空间中,使用的是直接内存)。需要注意的是,JDK7
及以后,将字符串常量池放在了堆空间。
1.1 constant_pool_count
常量池计数器
- 由于常量池的数量不固定,所以设置了两个字节来表示常量池中有多少常量。
- 常量池计数器的类型是
u2
,从1
开始,表示常量池中有多少项常量。constant_pool_count =1
表示的是常量池中有0
个常量项。 - 如下图所示的例子,红色框框出的两个字节是
16
进制的值,转换为十进制为22
,说明这个Class
文件中的常量池中有22 - 1 = 21
个常量。 - 第
0
项常量表示的是“不引用任何一个常量池项目”。
1.2 constant_pool
常量池表
- 常量池是一种表结构,以
1 ~ constant_pool_count - 1
为索引,表示有多少个常量项。 - 常量池
主要
存放字面量
和符号引用
。
- 常量池中每一项的第一个字节是类型标记,用于确定该项的格式,这个字节称为
tag byte
。如图所示,如果tag byte
是10
,表示的就是这一项常量存放的是类中方法的符号引用。常量池中能够存放的数据类型如下图所示:
1.2.1 字面量和符号引用
- 常量池主要存放字面量和符号引用。如下图所示,字面量包括文本字符串和声明为
final
的常量。符号引用包含类和接口的全限定名、字段的名称和描述符、方法的名称和描述符。
- 全限定名:全类名中的
.
替换成/
,多个全限定名之间使用分号分隔。 - 简单名称:字段或者方法的名称。例如
add()
方法和num
字段的简单名称分别为add
和num
。 - 描述符:用于描述字段的数据类型、方法的参数列表、方法的返回值。基本数据类型以及
void
类型都用一个字符表示,而对象类型则用字符L
加对象的全限定名来表示。
描述符如下表所示。解释一点,一维数组用[
表示,二维数组用[[
表示,以此类推。
补充说明: - 虚拟机在加载
Class
文件的时候才会进行动态链接(将符号引用转换成直接引用的过程)。Class文件中不会保存各个方法和字段最终的内存信息。 - 符号引用就是一组符号,与内存无关。
- 直接引用是与内存相关的,它指向了某块内存。
更多JVM文章请访问我的JVM专栏:
https://blog.csdn.net/u011069294/category_10113093.html