运行时常量池与class文件常量池本质是同一数据在不同阶段的形态,前者是类加载后驻留元空间的动态映射区,支持解析符号引用、运行时新增条目;后者是编译生成的.class文件中只读静态表,仅含字面量和符号引用。

运行时常量池和Class文件常量池本质是同一份数据在不同阶段的形态,区别核心在于“静态存储”与“动态加载”,而非结构本身。
Class文件常量池:编译后固化在磁盘上的只读表
它是.class文件的一部分,以二进制格式存在磁盘中,结构严格遵循JVM规范(如CONSTANT_Utf8、CONSTANT_String等条目类型)。内容完全由编译器生成,不可修改,包含两类数据:
- 字面量:如字符串字面量"hello"、整数123、final修饰的常量值
- 符号引用:如类全限定名java/lang/Object、方法名toString、字段描述符I(int)等逻辑标识
这个常量池不占用JVM运行时内存,只是字节码的元数据仓库。
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
运行时常量池:类加载后驻留在元空间的动态映射区
当类被ClassLoader加载时,JVM会把Class文件常量池的内容整体复制到内存中,形成运行时常量池,从JDK 8起它位于元空间(Metaspace),不再是永久代(PermGen)。
- 符号引用会被逐步解析为直接引用(如方法入口地址、Klass指针),这个过程叫动态链接
- 部分条目可运行时新增,比如通过String.intern()加入的字符串引用,或动态生成的Lambda调用点
- 它是一块逻辑上独立、每个类独有的区域,但实际共享元空间的内存管理
关键区别不在“结构”,而在生命周期与语义
两者条目类型一一对应,但语义已变:
- Class常量池里的CONSTANT_String #2只是指向一个UTF-8字节序列的索引;而运行时常量池里同一编号位置可能存的是堆中某个String对象的引用
- Class常量池中的CONSTANT_Class #3记录的是类名字符串;运行时常量池中它已被解析为指向对应java.lang.Class实例的Klass指针
- 运行时常量池支持运行期扩展(如invokedynamic引导方法注册),Class常量池完全静态
字符串常量池是独立存在、常被混淆的第三部分
它不是运行时常量池的子集,而是JVM单独维护的一块哈希表结构,自JDK 7起位于堆内存。运行时常量池中的字符串符号引用,在首次使用时可能触发intern操作,将对应String对象放入字符串常量池并返回其引用——这是两个池协同工作的典型场景,但物理上分离、管理机制不同。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










