Java中字符串常量池属方法区还是堆?是否含对象及可被GC?
JVM字符串常量池(SCP)常见疑问解析
一、SCP的存储位置:不同JDK版本有差异
这也是你查到不同说法的核心原因——存储位置随JDK版本发生了变化:
- JDK 1.6及更早版本:字符串常量池属于方法区的运行时常量池,而方法区的实现是永久代(PermGen)。
- JDK 1.7:字符串常量池从永久代移到了堆内存中,此时运行时常量池仍在永久代,但SCP已经独立出来放在堆里。
- JDK 1.8及之后:永久代被元空间(Metaspace)替代,运行时常量池移到元空间,但字符串常量池依旧保留在堆内存中。
二、SCP的构成:分版本有不同存储形式
- JDK 1.6:SCP中直接存储字符串字面量对应的String对象,这些对象和普通堆对象物理隔离,存在永久代里。
- JDK 1.7及之后:SCP中存储的是指向堆中String对象的引用,字符串字面量对应的实际对象放在堆的普通区域(年轻代/老年代)。
简单说,不管哪个版本,字符串字面量都会和SCP关联,但存储形式因版本不同有区别。
三、SCP中对象的垃圾回收:取决于存储位置和引用情况
- JDK 1.6:因为SCP在永久代,永久代GC触发条件苛刻(比如Full GC),所以里面的字符串对象很难被回收,基本常驻内存。
- JDK 1.7及之后:SCP在堆里,只要字符串对象没有被其他强引用持有(比如代码中无变量指向它,或对应类加载器被回收),GC触发时就会被正常回收。
比如动态生成的字符串调用intern()加入SCP后,若后续无任何引用指向它,这个字符串对象就能被GC回收。
内容的提问来源于stack exchange,提问作者Nitesh Agrawal
相关产品推荐
相关产品推荐

