2013-03-10 105 views
17

我在阅读有关垃圾回收的问题,当我搜索字符串文字垃圾回收时,我感到困惑的搜索结果。字符串文字的垃圾回收

我需要澄清以下几点:如果字符串被定义为在编译时文字

  1. [e.g:String str = "java"]那么这将是垃圾回收?

  2. 如果使用实习方法[例如:String str = new String("java").intern()]那么它会被垃圾收集?它也将被视为与第1点中的字符串字面值不同。

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

+2

1 - http://stackoverflow.com/questions/2202162/garbage-collection-and-strings; 2 - http://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java; 3 - String a = new String(“asd”) - >“a”引用将被垃圾回收,但只是对“asd”的引用,并且“asd”将永远存在。 – user1050755 2013-03-10 15:54:52

+0

如果你搜索更多,你会发现提到的地方使用实习生创建的字符串文字可以垃圾收集,因为他们使用弱参考,但我不能确认它,这就是为什么我张贴的原因,因为有很多混合的反应。 – Lokesh 2013-03-10 15:57:50

回答

18

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

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

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

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

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

然而,实习是不相同的字符串字符串文字可以垃圾收集一旦变得无法访问。 PermGen空间在所有最近的HotSpot JVM上收集的垃圾。 (现有到Java 8 ...而下降的PermGen完全。)

而且将它从字符串文本区别对待在点1

否...因为它是相同的对象字符串文字。

事实上,一旦你明白发生了什么,很明显字符串文字也没有被特别处理。这只是“可达性”规则的应用...

有些地方提到文字将被垃圾收集只有当String类将被卸载?这是否有意义,因为我认为String类不会被卸载。

你说得对。这没有意义。说这些来源是不正确的。 (如果您发布了一个URL,以便我们可以阅读他们正在说的内容,这将对您有所帮助...)

+1

对于#1,当你说代码对象包含对字符串文字的引用时,你指的是什么? – Mercenary 2013-11-12 14:00:59

+4

代码对象(字节码或本机编译)中的某处会有指令需要获取对应于字面值的String对象的引用。引用嵌入代码本身,或者将其存储在与代码关联的专用框架中。无论哪种方式,只要代码*可以被执行,引用就是“可到达的”。 – 2013-11-13 05:10:29

+0

谢谢。而且,是JVM中方法区域的字符串实习池部分? – Mercenary 2013-11-13 10:30:44

9

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

欲了解更多permgen,this是一个体面的主题概述。 (注意:该链接转到与产品相关的博客,我与博客,公司或产品没有任何关联,但博客条目非常有用,并且与产品无关。 )

+2

这是不正确的。 PermGen空间>>是“垃圾收集。 – 2013-03-10 16:07:07

+0

你当然是对的。我的意图只是说,在正常情况下,分配给permgen的数据不会得到GC,但我误解了。稍微改写一下。 – jacobm 2013-03-10 16:12:12

+0

事实上,深入挖掘,我发现被拦截的字符串不会被垃圾回收。 (这不是因为permgen空间,这是由于'String#intern'的实现。)改变我的答案以反映这一点。 – jacobm 2013-03-10 16:38:47

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

你可以给我一个例子,可以卸载字符串吗?因为我相信字符串文字也必须在Java类中使用,因为字符串文字是常量,卸载可能需要根据我的知识卸载CLassLoader。你同意吗? – Lokesh 2013-03-10 16:04:51

+0

根据我的知识,字符串文字不能以编程方式卸载。当程序终止时,它们将被卸载或销毁。 – fredrik 2013-03-10 16:06:33

+1

@fredrik - 如果已经动态加载的类被卸载,它们也可以被垃圾回收。当JVM运行正常时,可能会发生这种情况。 – 2013-03-10 17:27:59

-3

intern()方法检查字符串池中对象的可用性。如果对象/文字可用,则将返回其引用。如果文字不存在于池中,则将对象加载到perm区域(String pool)中,然后返回对其的引用。我们必须明智地使用intern()方法。

+0

根据定义,文字总是在游泳池中。 – EJP 2017-11-19 10:19:18