java中字符串常量池自jdk 7起物理位于堆内存,逻辑上由stringtable独立管理,存储字符串引用而非对象本身;jdk 6在永久代,jdk 8+仍驻堆中未进元空间。

Java中字符串常量池(String Table)自JDK 7起,**物理上明确位于堆内存(Heap)中**,不是方法区、永久代或元空间。
JDK 7 及以后:常量池在堆里,但逻辑独立
从JDK 7开始,HotSpot JVM将字符串常量池从永久代(PermGen)整体迁移至堆内存。它不再是方法区的一部分,而是堆内一个由StringTable管理的专用区域:
- StringTable本质是一个哈希表,默认初始大小为60013个桶(可通过-XX:StringTableSize调整)
- 它存储的是字符串对象的引用,而非字符串对象本身;真正的字符串实例(如char[]或byte[]数组)也分配在堆的普通区域
- 虽然在堆中,但它受JVM特殊管理——比如GC时仅在满足条件(如引用不可达、且无强引用指向)时才可能被清理
JDK 6 及之前:在永久代(PermGen),属于方法区
那时字符串常量池是方法区(具体实现为永久代)的一部分:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 常量池中直接存放字符串对象实例
- 永久代空间小、难调优,大量字符串容易触发java.lang.OutOfMemoryError: PermGen space
- 这也是JDK 7迁移的根本动因
JDK 8 及以后:仍在堆中,永久代已彻底消失
JDK 8用元空间(Metaspace)替代永久代,但字符串常量池没有跟着去元空间:
- 元空间只存类元数据(Class对象、方法、字段等),不存任何字符串
- StringTable继续驻留在堆内存,位置和行为与JDK 7一致
- 运行时常量池(Runtime Constant Pool)仍属方法区(现由元空间实现),但其中的字符串字面量解析最终都指向堆中的StringTable
怎么验证它在堆里?
可通过JVM参数配合工具观察:
- 添加-XX:+PrintGCDetails -verbose:gc,GC日志中若出现对StringTable的清理记录,说明它参与堆GC周期
- 使用jmap -histo:live
,能统计到String对象数量,其地址范围落在堆区间内 - JDK 7+ 的jcmd
VM.native_memory summary 中,StringTable归类在“Internal”或“Heap”子项下,而非“Metaspace”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










