运行时常量池中的字面量存“值”,符号引用存“名字”;字面量是编译期确定的不可变数据如"abc"、100,直接使用或创建对象;符号引用是类、方法、字段的文本描述如java/lang/String.length:()I,需解析为直接引用后才能调用。

运行时常量池里的字面量和符号引用,本质是两类不同用途的“标识信息”,一个存的是“值”,一个存的是“名字”。
字面量:编译期就确定的具体值
字面量是代码里直接写出的不可变数据,比如 "abc"、100、'x'、true。它们在编译时就被写进 .class 文件的常量池 中,类加载后进入运行时常量池。
- 字符串字面量(如 "hello")会同时进入字符串常量池(JDK 7+ 在堆中),保证相同内容只有一份实例
- 整数字面量(-128 到 127)会被包装类缓存,超出范围则每次 new 都新建对象
- 字面量本身不指向内存地址,只是原始数据;使用时 JVM 直接取用或基于它创建对象
符号引用:编译期记录的“逻辑名称”
符号引用不是值,而是对类、方法、字段的“文本描述”,比如 java/lang/String.length:()I 或 com/example/MyClass.fieldName:I。它只在编译阶段存在,靠名字定位目标,不依赖内存布局。
- 包含三类:类/接口的全限定名、字段的名称与描述符、方法的名称与描述符
- 类加载的“解析阶段”才会把符号引用转成直接引用(比如方法入口地址、字段内存偏移量)
- 延迟解析:只有真正执行到调用指令(如 invokestatic、getstatic)时才触发,支持动态链接和多态
二者关系:静态存档 → 运行活化
Class 文件常量池里,字面量和符号引用都是静态的、只读的文本条目。一旦类被加载,这些内容整体搬入运行时常量池——字面量基本保持原样可用,而符号引用则逐步“活化”为可执行的直接引用。
立即学习“Java免费学习笔记(深入)”;
- 同一个字符串字面量,在多个类的 Class 常量池里各存一份,但运行时常量池(及字符串常量池)中通常只保留一个实例
- 符号引用在未解析前不能调用,解析失败会抛 NoClassDefFoundError 或 NoSuchMethodError
- 运行时还能新增:通过 String.intern() 或 invokedynamic 动态加入新项
字符串是个特例:横跨两类
字符串既属于字面量(如 "test" 是编译期确定的值),又常作为符号引用的组成部分(如类名 "java/lang/Object")。但它的驻留机制让它拥有双重身份:
- 双引号创建的字符串,先查字符串常量池,命中则复用;未命中则在堆中新建并登记
- intern() 显式触发驻留,确保该字符串在字符串常量池中有唯一引用
- 注意:字符串常量池自 JDK 7 起独立于运行时常量池,位于堆内存,但逻辑上仍与其协同工作


















