我正在为缓存实现测试 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"))
那么它就是。
我使用 Eclipse Memory Analyzer 查看堆内容,在这两种情况下,除了 Soft 链之外没有其他引用链。
如果有人对我感兴趣的这种奇怪行为有解释。
最佳答案
这很简单。源代码中出现的字符串是intern ed,即保存在一个特殊的池中,并且没有机会收集它,因为它被您的方法代码引用。再次调用 setName
时需要它,所以它显然不是垃圾。
new String("name")
的情况非常不同,因为它创建了原始字符串的副本。实际上,自 this change 以来就没有必要使用这个构造函数了。到 String.substring
。
我猜 Eclipse 内存分析器不会显示字节码中包含的引用(因为没有人真正需要它)。
关于java - SoftReference<String> 内存不足时未进行垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21615718/