字符串文字的垃圾收集

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

我需要澄清以下几点:

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

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

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

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

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

代码对象可能无法访问,但只有当它们被动态加载时……它们的类加载器才会被销毁。

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

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

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

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

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

事实上,一旦你理解了正在发生的事情,很明显字符串文字也没有特别对待。 它只是“可达性”规则的应用……

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

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

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

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

  1. 只要程序在内存中,文字字符串就会保留在内存中。
  2. str将被垃圾收集,但它创建的文字不会。
  3. 这很有道理,因为卸载程序时会卸载字符串类。

intern()方法检查String池中对象的可用性。 如果object / literal可用,那么将返回它的引用。 如果池中没有文字,则在perm区域(String池)中加载对象,然后返回对它的引用。 我们必须明智地使用intern()方法。