String字面值已声明但未被引用是否符合G'ed的条件?

时间:2013-12-24 10:55:20

标签: java string garbage-collection

据我所知,如果在String池中找到String,则intern方法应该从String池返回String,否则将在String池中添加new string object并返回此String的引用。

String s = "a";
s = "b";
String str = new String("a").intern();

在这种情况下会发生什么......是否存在两种情况

  1. 直到“a”不是垃圾收集,而String str = new String("a").intern();执行str会引用此“a”
  2. 如果“a”是Gc'ed,那么将创建一个新对象,str将引用一个新的“a”;
  3. 或“a”从未符合垃圾回收的条件?

4 个答案:

答案 0 :(得分:3)

这在不同的JVM中是不同的。例如,

OpenJDK / Hotspot Java 6:字符串文字在PermGen和AFAIK中,只在Full GC上清理(不仅仅是终身空间的主要集合)

OpenJDK / Hotspot Java 7:字符串文字在Heap中,可以随时收集它们,但我怀疑它们是由代码中使用的PermGen持有的。

OpenJDK / Hotspot Java 8:没有PermGen所以即使由现在位于堆中的Classes保存,也应该更自由地清理字符串。

1)只有一个字符串文字,并且在没有引用它之前它不会被GC,也可能在cde中,这可能是在ClassLoader卸载时,如果有的话。

2)你创建的第一个"a"和第二个"a"以及第三个可能是不同的字符串,如果它们之间有GC。

答案 1 :(得分:2)

当Java包含的类超出范围时,Java规范不会正式禁止String常量的垃圾收集,但是any two String literals with identical contents must refer to the same String objectString#intern()的返回值必须是同一个对象这将由具有相同内容的文字引用。

给定的JVM是否实际上从运行时常量池中垃圾收集String个对象是一个实现细节,但给定这些要求的String个实例的可达性规则是{{1如果任何可到达的变量包含对它的引用或者加载了任何具有该文字的类,则可以在常量池中访问它。

在您的特定情况下,String文字String符合以下条件进行垃圾回收:

  • 消除了对它的所有引用(包括"a"s的第一个值,它引用同一个对象,它位于常量池中)和
  • 卸载内容为str的{​​{1}}常量的所有类。

答案 2 :(得分:2)

  1. “a”由编译器和类加载器放在常量池中。
  2. 在没有对其进行引用之前,不能对其进行垃圾回收。
  3. 's'是对第一行代码中“a”的引用。
  4. 您的第二行代码会产生另一个引用。
  5. 因此,当“s”或“str”可达时,“a”不能被垃圾收集。
  6. 因此,你的最后一个问题编号(2)没有意义,因为它的前提条件不可能发生,

答案 3 :(得分:0)

正如其他人所提到的,行为是一个实现细节。找到的一种方法是仅使用WeakReference然后force a garbage collection引用字符串,并查看WeakReference是否已被清除。

以下是一些示例代码:

// Only keep a weak reference to a
String str = "a";
WeakReference<String> strRef = new WeakReference<String>(str);
str = null;

// Attempt to force GC
Object obj = new Object();
WeakReference<Object> ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
  System.gc();
}

// Wait a bit a second to make sure GC has actually run
Thread.sleep(1000);
// Print the result
if (strRef.get() == null) {
  System.out.println("String \"a\" has been garbage collected");
} else {
  System.out.println("String \"a\" has not been garbage collected");
}

在使用JavaSE-1.7的我的机器上,String不是垃圾回收。