众所周知,字符串常量池从JDK1.7开始从方法区中移到了堆内存(常见的笼统说法),堆内存常规理解是划分为了新生代和老年代,JDK1.7还有堆中永久代实现方法区,字符串常量池从方法区移到堆中应该是不会继续在永久代,那么是新开辟了区域还是放入新老年代区域?
JDK8变化是移除堆中永久代,方法区采用本地内存元空间实现,字符串常量池还是在堆内存,具体在堆中哪个区域本人不太理解?
此提问经过修改,以下是个人理解,有误的地方望大佬指正,感谢!
从JDK1.7开始,字符串常量池是一个叫StringTable的哈希表结构,里面存的是缓存对象的引用地址,被缓存的字符串对象在堆内存中,会经历垃圾回收,young gc的时候,StringTable做为GC Root,被缓存对象继续存活,full gc的时候,StringTable不作为GC Root,缓存对象可以被回收,清理StringTable。个人问题其实是StringTable这个东西是开辟在哪里,比较明确是的在堆中,那么它在堆中是有一块独立空间吗?感觉应该是的。
字符串常量池在堆中确实有一个独立的空间,它与堆的其他部分是分开的。字符串常量池中的对象也是在新生代中创建的,但它们通常会很快进入永久代(Java 6及更早版本)或元空间(Java 7及更高版本),这取决于JDK的版本。
在Java 6及更早版本中,字符串常量池存储在永久代中。在这种情况下,字符串常量池中的对象仍然是在新生代中创建的,但是它们可能会很快进入永久代。这是因为在Java 6中,永久代用于存储类的元数据和其他静态数据。因此,将字符串常量池存储在永久代中是有意义的,因为字符串常量通常被认为是静态的数据。
在Java 7及更高版本中,永久代已被元空间取代。元空间不是Java堆的一部分,而是使用本地内存来实现的。因此,在这种情况下,字符串常量池仍然存储在堆中,但不再是永久代,而是元空间。这意味着,字符串常量池中的对象仍然是在新生代中创建的,并且不会像在Java 6中那样很快进入永久代。
在任何情况下,字符串常量池中的对象都不会像普通对象那样被垃圾回收器回收,而是一直存活在堆中。这是因为字符串常量池中的对象是被全局引用的,因此只有在类被卸载时才会被释放。