如果字符串池(String Pool)的内存用尽会发生什么?

11

如果字符串池中有很多字符串字面量并且它的内存用尽了,会发生什么?它会增长吗?如果会,那么它是如何增长的?如果不会增长,那么如果我尝试创建更多的字符串字面量会发生什么?


1
如果常量池中的字符串不再需要,它们可以被垃圾回收。 - Hiren
1
@Hiru,但JVM不是会保留字面量以便重复使用,从而防止其被垃圾回收吗? - Milan Pandey
1个回答

18

首要问题 - 字符串池不包含字符串字面量

字符串池是指向字符串对象的引用集合。

当您写下String = "hello"时,它会在堆上创建一个字符串对象"hello",并将一个对此对象的引用放置在字符串文字池中(前提是没有已命名为“Hello”的堆对象)

注意事项“hello”被添加到相应类的常量池中。 因此,只有在卸载类之后才能进行垃圾回收。因此,在卸载类时,该对象得到GC。

会发生什么?

字符串池是通过称为字符串规范化的过程进行汇集的。这是一个弱哈希映射。当键或值没有其他引用时,此弱哈希映射会自动清除映射。也就是说,该字符串将从JVM中进行垃圾回收。

它会增长吗?

不会增长大小-它是编译时常量

它如何增长?

您需要在编译时指定-XX:StringTableSize=N,其中N是字符串池映射的大小

最后,您的问题:

如果字符串池内存不足会发生什么?

最简单的答案是:从Java 7开始,您将获得 java.lang.OutOfMemoryError:java.lang.OutOfMemoryError:Java堆空间。在旧版本的Java中(如6),则为java.lang.OutOfMemoryError:PermGen space


1
+1 对你回答的后半部分表示赞同,但是我对前半部分有些困惑,“字符串池没有字符串字面量”。我读过,如果我使用new操作符创建一个字符串,它会在堆上创建对象,而字面量则保留在池中。这有点令人困惑。你能帮我解释一下吗? - Milan Pandey
1
-XX:StringTableSize选项可以在JVM启动时指定,而不是编译时。表格大小并不决定可以存储多少字符串。存储更多的字符串会增加哈希碰撞的机率,但是表格会处理碰撞,只是查找变得不那么高效。 - Holger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接