我正在阅读垃圾收集,当我搜索字符串文字垃圾收集时,我的搜索结果令人困惑。
我需要澄清以下几点:
如果在编译时将字符串定义为文字[例如:String str = "java"
]那么它是否会被垃圾收集?
如果使用实习方法[例如:String str = new String("java").intern()
]那么它会被垃圾收集吗?它也将与第1点中的字符串文字区别对待。
有些地方提到只有在卸载String
类时才会对文字进行垃圾收集?它是否有意义,因为我认为String
类不会被卸载。
答案 0 :(得分:19)
如果字符串在编译时被定义为文字[例如:
String str = "java";
]那么它会被垃圾收集吗?
可能不是。代码对象将包含对表示文字的String
对象的一个或多个引用。因此,只要代码对象可以访问,String
对象就是。
代码对象可能无法访问,但只有当它们被动态加载时...才会破坏它们的类加载器。
如果我使用实习方法[例如:
String str = new String("java").intern()
]那么它会被垃圾收集吗?
intern
调用返回的对象将是表示"java"
字符串文字的同一对象。 ("java"
字面值是在类加载时实现的。当您在代码片段中实现新构造的String
对象时,它将查找并返回先前实例化的"java"
字符串。)< / p>
但是,与字符串文字不相同的实习字符串一旦无法访问就会被垃圾收集。在所有最近的HotSpot JVM上收集了PermGen空间 垃圾。 (在Java 8之前......完全丢弃了PermGen。)
它也将与第1点中的字符串文字区别对待。
否...因为它与字符串文字是同一个对象。
事实上,一旦你理解了正在发生的事情,很明显字符串文字也没有特别对待。它只是“可达性”规则的应用......
有些地方提到只有在卸载
String
类时才会对文字进行垃圾收集?是否有意义,因为我认为String
类不会被卸载。
你是对的。这没有意义。那些说不正确的消息来源。 (如果您发布了一个URL,以便我们可以自己阅读他们所说的内容,那将会很有帮助。)
答案 1 :(得分:10)
在正常情况下,字符串文字和类都被分配到JVM的永久代(“PermGen”)中,并且通常不会被收集。被拦截的字符串(例如mystring.intern()
)存储在permgen中String
类所拥有的内存池中,曾经的情况是,激进的实习可能会导致空间泄漏,因为字符串池本身就存在即使没有其他引用存在,也引用每个字符串。显然这已不再适用,至少从JDK 1.6开始(参见例如here)。
有关permgen的更多信息,this是对该主题的一个不错的概述。 (注意:该链接指向与产品关联的博客。我与博客,公司或产品没有任何关联,但博客条目很有用,与产品无关。 )
答案 2 :(得分:0)
str
将被垃圾收集,但它的文字不会被创建。答案 3 :(得分:-3)
intern()
方法检查String池中对象的可用性。如果object / literal可用,那么将返回它的引用。如果池中没有文字,则在perm区域(String池)中加载对象,然后返回对它的引用。我们必须明智地使用intern()
方法。