现代JVM中StringTable垃圾回收核心是按可达性判断:字符串对象在堆中,仅当无强引用指向时才被GC清理;JDK7起移至堆内存,受Full GC或G1/ZGC并发标记阶段管理,可通过-XX:+PrintStringTableStatistics等参数观察调优。

现代 JVM 中字符串常量池(String Table)的垃圾回收,核心不是“清空池子”,而是按对象可达性判断是否回收——只要池中某个字符串对象不再被任何强引用持有,它就可能在合适的 GC 阶段被清理掉。
字符串常量池现在就在堆里
JDK 7 起,String Table 从永久代移到了堆内存。这意味着它和普通 Java 对象一样,受堆 GC 管理,不再依赖低效的永久代 Full GC。池本身是一个哈希表(默认大小 60013),存的是对字符串对象的引用,而字符串对象本身也分配在堆中。
- 类加载时出现的字面量(如 String s = "abc")会尝试入池,对象实际创建在堆上
- new String("def").intern() 也是把堆中已有对象的引用放入池,不是复制新对象(JDK 7+)
- 池中不存“字符串内容”,只存指向堆中字符串实例的引用
回收只看“有没有人还在用”
能不能回收,唯一标准是:这个字符串对象是否还存在一条从 GC Roots 出发的强引用链。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 局部变量、静态字段、集合容器(如 Map 缓存)、线程栈帧中仍持有该字符串 → 不可回收
- 所有显式引用都已失效(变量出作用域、设为 null、缓存被清除)→ 可能被回收
- 类卸载后,若某字符串仅由该类的字面量引用,也会因 Class 引用消失而变得不可达
哪些 GC 会真正处理它
String Table 不参与 Minor GC,它的清理发生在更彻底的回收阶段:
立即学习“Java免费学习笔记(深入)”;
- Full GC:传统方式,遍历整个堆 + 方法区/元空间,做完整可达性分析
- G1 / ZGC / Shenandoah 的并发标记阶段:这些收集器在并发标记时会扫描常量池中的引用关系
- 元空间类卸载配合触发:当类被卸载,其关联的字符串若无其他引用,也会一并变为废弃常量
怎么观察和调优
避免靠猜,用 JVM 参数验证行为:
- -XX:+PrintStringTableStatistics:每次 GC 后打印池大小、条目数、平均链长,看是否持续增长
- -XX:StringTableSize=60013:设为质数,减少哈希冲突,提升查找与清理效率
- jstat -gc <pid> 结合老年代使用率变化,辅助判断大量字符串是否被成功回收

















