运行时常量池是方法区(jdk 8+为元空间)的一部分,每个类独有,存储编译期字面量和符号引用,支持动态解析与有限扩充(如intern()),但不存字符串对象本身,而是与堆中字符串常量池协作。

运行时常量池是方法区(JDK 8+ 为元空间)的一部分,它在类加载阶段被创建,用于存放编译期生成的各种字面量和符号引用,并在运行期动态解析、存储和复用。
运行时常量池从 class 文件常量池而来
每个 class 文件都有一个常量池表(Constant Pool Table),里面存着编译时确定的字符串字面量、类/字段/方法符号引用、数字常量等。当类被加载进 JVM 时,这部分内容会被复制到运行时常量池中,并完成部分解析(比如类名转为 Klass 指针,方法引用转为直接入口地址)。未解析的符号引用会在首次使用时才动态链接。
它不是只读的,支持运行期动态添加
与 class 文件常量池不同,运行时常量池是可变的。最典型的例子就是 String.intern():
- JDK 7 及以后,字符串常量池被移到堆中,而运行时常量池仍位于方法区(元空间);
- 调用
"abc".intern()时,JVM 会检查字符串常量池中是否已存在值为"abc"的 String 对象:
✓ 若存在,直接返回其引用;
✗ 若不存在,则将该字符串对象(或其副本)加入字符串常量池,并返回该引用。
这个过程会间接影响运行时常量池中对字符串的符号引用解析结果。
它和字符串常量池是两个独立但协作的结构
- 运行时常量池(Runtime Constant Pool)属于方法区,保存的是 class 文件中所有常量项的运行时表示,包括类、方法、字段的符号引用,也包含对字符串字面量的引用(如
#2 = String "hello"); - 字符串常量池(String Pool)是专门管理字符串实例的哈希表,位于堆中(JDK 7+),只存 String 对象的引用;
- 当运行时常量池里某一项是字符串字面量时,它实际指向的是字符串常量池中的那个 String 实例,而不是堆里重复创建的新对象。
内存异常风险需留意
- 运行时常量池属于方法区/元空间,如果大量使用
intern()或动态生成类(如 CGLIB、ASM),可能导致元空间溢出,抛出java.lang.OutOfMemoryError: Metaspace; - 可通过
-XX:MaxMetaspaceSize控制上限,用-XX:+PrintGCDetails观察元空间回收情况。
基本上就这些。










