运行时常量池是方法区(jdk 8+为元空间)中逻辑组织的常量数据结构,按值共享字面量、暂存符号引用、支持有限动态添加,本质是存储描述信息的元数据容器而非对象仓库。

运行时常量池不是一块连续的物理内存区域,而是方法区(JDK 8+ 是元空间)中逻辑组织的一组常量数据结构。它对字面量和符号引用采用不同策略存储和管理。
字面量:按值共享,多数驻留堆或元空间
字面量如字符串"abc"、整数123、布尔true等,在类加载时从Class常量池复制进来。但实际存储位置取决于类型:
- 字符串字面量:JDK 7起统一存入堆中的字符串常量池(String Pool),是一个哈希表结构,相同内容只保留一个对象实例;
- 基本类型字面量(int/long/float/double/boolean/char):直接作为常量项存于运行时常量池中,占用元空间(JDK 8+)或永久代(旧版),不创建对象;
- null字面量:以CONSTANT_Null_info形式存在,不分配内存空间,仅作占位标识。
符号引用:暂存名称描述,延迟解析为直接引用
符号引用本身不指向真实内存地址,而是以文本形式保存类、字段、方法的逻辑标识:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 类全限定名(如java/lang/String)、字段名与描述符(如value:[C)、方法名与签名(如length:()I)均以CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等条目形式存入;
- 这些条目在类加载的“解析”阶段才被替换成直接引用——比如类指针、方法入口地址、字段在对象中的偏移量;
- 未被触发解析的符号引用始终保留在运行时常量池中,保持原始字符串形态。
动态性支持:运行时可新增,但机制受限
运行时常量池允许在程序执行中添加新常量,但仅限特定场景:
- String.intern():若字符串内容不在字符串常量池中,则将其对象引用加入,并让运行时常量池中对应CONSTANT_String_info指向该堆对象;
- invokedynamic指令:配合Bootstrap Method动态生成方法句柄,其生成的常量项会注册进运行时常量池;
- 普通代码无法直接向运行时常量池写入任意新条目,JVM不开放底层API供用户随意插入。
存储本质:元数据容器,非对象仓库
运行时常量池存储的是“描述信息”而非“运行实体”:
- 它不存放String对象本身(对象在堆),只存指向它的引用或名称;
- 它不存放Method对象(在元空间方法区),只存方法名、签名等符号;
- 所有条目由JVM内部结构管理,开发者不能通过new或反射直接操作其内存布局。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










