字符串常量池通过“内容去重+引用共享”实现内存优化,本质是堆中默认容量60013的哈希表,以字符串内容为key、对象引用为value,支持o(1)查找;字面量复用同一实例(==为true),new则总在堆新建对象(==为false),依赖string不可变性保障线程安全与共享可靠。

字符串常量池通过“内容去重 + 引用共享”实现内存优化,核心是避免重复创建相同内容的字符串对象。
相同内容只存一份,所有引用共用一个对象
Java中大量出现重复字符串(如日志级别"INFO"、HTTP状态码"200"、配置项"timeout"),若每次创建都分配新对象,堆内存会迅速堆积冗余实例。常量池像一个哈希表,以字符串内容为key,存储唯一对象的引用。只要字面量相同(如"hello"),JVM就复用已有实例,不新建。
- 字面量方式:String s1 = "hello"; String s2 = "hello"; → s1 和 s2 指向堆中同一个对象,== 返回 true
- new 方式:String s3 = new String("hello"); → 总是在堆上新建对象,即使池中已有,== 返回 false
底层靠哈希表实现 O(1) 查找,高效支撑复用
从 JDK 1.7 起,字符串常量池位于堆内存中,底层是一个默认容量为 60013 的哈希表(可通过 -XX:StringTableSize 调整)。插入或查找时,JVM 计算字符串内容的 hash 值,快速定位是否存在。这种设计让“检查是否已存在”几乎无性能损耗,使得大规模复用在运行时依然高效。
- key 是字符串的内容(字符序列)
- value 是堆中该字符串对象的引用(不是对象本身,更省空间)
- 避免了线性遍历,支撑每秒数万次的字符串字面量加载
节省的不只是对象本身,还有 GC 压力和初始化开销
每个 String 对象包含对象头、字段(如 value 数组引用、hash 缓存)、以及底层 char[] 或 byte[] 数组。重复创建千个"OK",就要分配千份这些结构;而池化后,只保留一份数组和一个对象实例。
- 减少堆内存占用,尤其在解析 JSON、处理 HTTP Header、缓存城市/国家名等场景效果显著
- 降低 Minor GC 频率——临时字符串对象越少,新生代存活对象越少
- 跳过重复的对象构造和字段赋值过程,提升字符串初始化速度
不可变性是安全共享的前提
String 类被设计为 final 且内部字符数组不可外部修改,保证了“共享一个对象”不会引发数据竞争或意外变更。就像快递柜里的密封包裹,谁取都不会影响别人拿到的内容——这使得 JVM 敢于让成百上千个变量同时指向池中同一个字符串实例。










