String文字的垃圾回收
我正在阅读关于垃圾收集的内容,当我搜索字符串文字垃圾收集时,我正在混淆搜索结果。
我需要澄清以下几点:
如果一个字符串在编译时被定义为文字[例如: String str = "java"
],那么它会被垃圾收集吗?
如果使用实习方法[例如: String str = new String("java").intern()
],那么它将被垃圾收集? 它也将被视为与第1点中的字符串字面值不同。
有些地方提到,只有当String
类将被卸载时,文字才会被垃圾收集。 它是否有意义,因为我不认为String
类会被卸载。
如果在编译时将字符串定义为文字[例如: String str = "java";
]那么它会被垃圾收集?
可能不会。 代码对象将包含一个或多个对表示文字的String
对象的引用。 所以只要代码对象可访问, String
对象将会是。
代码对象可能无法访问,但只有在它们是动态加载的时候...而且它们的类加载器被破坏了。
如果我使用实习方法[例如: String str = new String("java").intern()
],那么它将被垃圾收集?
由intern
调用返回的对象将是表示"java"
字符串文字的相同对象。 ( "java"
文字是在类加载时被执行的,当你在你的代码片段中实习新构造的String
对象时,它将查找并返回以前被拦截的"java"
字符串。)
但是,与字符串文本不相同的interned字符串一旦变得无法访问就可以进行垃圾回收。 PermGen空间在所有最近的HotSpot JVM上进行垃圾收集。 (在Java 8之前......完全抛弃了PermGen。)
它也将被视为与第1点中的字符串字面值不同。
不......因为它与字符串文字是同一个对象。
事实上,一旦你明白发生了什么,很明显字符串文字也不是特别对待。 这只是“可达性”规则的一个应用。
有些地方提到,只有当String
类将被卸载时,文字才会被垃圾收集。 这是否合理,因为我不认为这个String
类会被卸载。
你是对的。 这没有意义。 说这些来源是不正确的。 (如果您发布了一个URL,以便我们可以阅读他们自己的意见,这将会很有帮助......)
在正常情况下,字符串文字和类都被分配到JVM的永久代(“PermGen”)中,并且通常不会被收集。 被执行的字符串(例如mystring.intern()
)被存储在permgen中的String
类所拥有的内存池中,并且曾经是积极的实习可能导致空间泄漏的情况,因为字符串池本身持有对每个字符串,即使没有其他参考存在。 显然这不再是真实的,至少从JDK 1.6开始(例如参见这里)。
有关permgen的更多信息,这是对该主题的一个体面的概述。 (注意:该链接转到与产品相关的博客,我与博客,公司或产品没有任何关联,但博客条目非常有用,并且与产品无关。 )
str
将被垃圾收集,但它创建的文字不会。