内存不足时,SoftReference <string>不会收集垃圾</string>

时间:2014-02-06 22:44:41

标签: java garbage-collection soft-references

我正在测试SoftReference的缓存实现,我发现了一个奇怪的行为:

我有一个setName(String name)方法,它通过SoftReference设置Graph对象的名称:

public void setName(String newName) {
    getData().name = new SoftReference<String>(newName,garbagedData);
}

(garbagedData是一个ReferenceQueue,在这个特殊问题中看起来并不重要。)

当我从主线程调用graph.setName("name");时,当à强制OutOfMemory错误时,引用指向的值不会被冒充,但如果我调用graph.setName(new String("name"))则它是。< / p>

我使用Eclipse Memory Analyzer查看堆内容,并且在两种情况下都没有其他参考链而不是Soft。

如果有人对这种奇怪的行为有解释,我感兴趣。

2 个答案:

答案 0 :(得分:2)

这很简单。出现在源代码中的字符串是intern,即保存在特殊池中,并且没有机会收集它,因为它是由您的方法的代码引用的。 <{1}}再次被调用时需要它,所以显然没有垃圾。

setName的情况非常不同,因为这会创建原始字符串的副本。实际上,从this changenew String("name"),不需要使用此构造函数。

我猜Eclipse Memory Analyzer没有显示字节码中包含的引用(因为没有人真正需要它)。

答案 1 :(得分:0)

您正在对String对象持有SoftReference。对于String对象,JVM管理String文字与String对象不同。

String a = new String("test");
String b = new String("test");

在此示例中,实例a和b是对不同对象的引用。

String a = "test";
String b = "test";

这里a和b都是对同一个String文字的引用。当您调用graph.setName(“name”)时,它正在创建对字符串文字的引用。引用字符串文字的字符串对象通常不被视为垃圾收集。这可以防止String对象被垃圾收集。

当你调用graph.setName(new String(“name”))时,它正在为新的String对象创建一个SoftReference。由于引用是新创建的对象而不是字符串文字,因此可以对其进行垃圾回收。

相关问题