10

在 Java 中,

字符串常量池中的字符串文字不会被垃圾收集,因为它们是从由运行时实例创建的引用表中引用的,以优化空间。

如果字符串字面量池的大小超过那么,由于字符串字面量池中的每个字符串都有引用,因此它将不符合 GC 的条件。JVM如何处理它?

4

2 回答 2

12

JavaRanch上对真实的代码示例进行了长时间的讨论。

一般输出如下:

  1. 如果在 RUNTIME 使用 String.intern() 将字符串添加到常量池,则可以在不再使用后对它进行垃圾收集。最有可能的是,字符串池只保留对添加字符串的软引用,从而允许对它们进行垃圾收集(不能确定,因为 String.intern() 是本机方法)。
  2. 如果一个字符串是一个COMPILE时间常数,则将其添加到相应类的常数池中。因此,只有在类卸载后才能对其进行垃圾回收。

您的问题的答案是:由于 String 常量而获得 OutOfMemoryError 的唯一方法是加载大量具有在编译时计算的许多字符串文字的类。然后你最终可以超过 PermGen 空间的最大大小。但这会在您将类加载到内存时发生(例如,启动应用程序、将项目部署到 WebServer、动态加载新库等)

于 2012-04-19T09:45:38.283 回答
3

当不再需要字符串文字时,可以收集它们。通常,如果它们出现在类中,这不是问题,因为如果您尝试加载大量类,例如 Maximum Perm Gen,您可能会达到其他限制。

一般来说,开发人员足够聪明,不会过度使用字符串字面量池,而是使用数据库或文件来加载大量数据(如果其大小不一)。

如果您大量使用 String.intern() 来尝试优化系统空间,则可能会引入问题。String.intern() 不是免费的,如果你在其中添加大量(数百万)字符串,它会变得越来越昂贵。如果这是一个性能问题,那么对于开发人员来说应该是相当明显的。

于 2012-04-19T09:09:21.710 回答