21

我正在阅读有关垃圾收集的信息,当我搜索字符串文字垃圾收集时,我的搜索结果令人困惑。

我需要澄清以下几点:

  1. 如果一个字符串在编译时被定义为文字 [eg: String str = "java"] 那么它会被垃圾收集吗?

  2. 如果使用实习生方法 [eg: String str = new String("java").intern()] 那么它会被垃圾收集吗?它也将与第 1 点中的字符串文字区别对待。

  3. 有些地方提到只有在String卸载类时才会对文字进行垃圾收集?这是否有意义,因为我认为String类永远不会被卸载。

4

4 回答 4

19

如果一个字符串在编译时被定义为文字 [eg: String str = "java";] 那么它会被垃圾收集吗?

可能不是。代码对象将包含一个或多个对String表示文字的对象的引用。所以只要代码对象是可访问的,String对象就会到。

代码对象可能无法访问,但前提是它们是动态加载的……并且它们的类加载器被销毁。

如果我使用实习生方法 [eg: String str = new String("java").intern()] 那么它会被垃圾收集吗?

调用返回的对象intern将与表示"java"字符串文字的对象相同。("java"文字在类加载时被实习。当您String在代码片段中实习新构造的对象时,它将查找并返回先前实习的"java"字符串。)

但是,与字符串文字不相同的实习字符串一旦变得无法访问,就会被垃圾回收。PermGen 空间在所有最近的 HotSpot JVM 上收集的垃圾。(在 Java 8 之前……它完全放弃了 PermGen。)

它也将与第 1 点中的字符串文字区别对待。

不......因为它与字符串文字是同一个对象。

事实上,一旦你了解了发生了什么,很明显字符串文字也没有被特殊对待。它只是“可达性”规则的应用......

有些地方提到只有在String卸载类时才会对文字进行垃圾收集?这是否有意义,因为我认为String该类永远不会被卸载。

你说的对。这没有意义。说那是不正确的消息来源。(如果您发布一个 URL 会很有帮助,这样我们就可以阅读他们自己所说的内容......)

于 2013-03-10T16:15:37.007 回答
10

在正常情况下,字符串字面量和类都分配到 JVM 的永久代(“PermGen”)中,通常永远不会被收集。被实习的字符串(例如mystring.intern())存储在 permgen 中的类所拥有的内存池中String,曾经有过激进的实习可能导致空间泄漏的情况,因为字符串池本身持有对每个字符串的引用,即使没有其他字符串存在参考。显然这不再是正确的,至少从 JDK 1.6 开始(参见,例如,here)。

有关 permgen 的更多信息,是对该主题的一个不错的概述。(注意:该链接指向与产品关联的博客。我与博客、公司或产品没有任何关联,但博客条目很有用,与产品没有太大关系。 )

于 2013-03-10T15:57:57.940 回答
0
  1. 只要程序在内存中,文字字符串就会保留在内存中。
  2. str将被垃圾收集,但创建它的文字不会。
  3. 这是非常有意义的,因为在卸载程序时会卸载字符串类。
于 2013-03-10T15:58:54.823 回答
-3

intern()方法检查字符串池中对象的可用性。如果对象/文字可用,则将返回它的引用。如果池中没有文字,则将对象加载到永久区域(字符串池)中,然后将返回对它的引用。我们必须intern()明智地使用方法。

于 2013-03-10T16:05:53.227 回答