在Java中,有一种称为WeakHashMap的数据结构,它将弱引用存储为键。 每当从内存中删除弱引用时,该条目都会从映射中删除。
如果我有一个数据结构,如堆栈或集合,我在其中存储弱引用,当弱引用从内存中取出时,它们的条目会自动删除吗?
下面是一个存储弱引用的堆栈示例。
Stack<WeakReference<Object>> objStack = new Stack<WeakReference<Object>>();
是的。你所描述的是一般的弱引用的属性,而不是具体的WeakHashMap
。
从 API :
假设垃圾回收器在某个时间点确定对象是弱可访问的。届时,它将以原子方式清除对该对象的所有弱引用......
迟到总比没有好。
这不是弱引用的工作方式。WeakReference
-object 将始终存在,但其get()
-方法可能会返回原始对象或null
(如果原始对象是 GC:ed)。
这意味着您的堆栈将始终包含一个WeakReference
对象。
这是我做的一个详细的测试(但是这取决于 JVM 在中间执行 GC,这可能会也可能不会"根据命令"发生 - 如果没有发生,请尝试添加更多System.gc()
:s):
public static void main(String[] args) {
// Set up
Object object = new Object();
final WeakReference<Object> weakReference = new WeakReference<>(object);
final Stack<WeakReference<Object>> references = new Stack<>();
references.add(weakReference);
// Before
System.out.println("Before:");
references.forEach(r -> {
System.out.println("Reference: " + r);
System.out.println("Object: " + r.get());
});
// GC
object = null;
System.gc();
System.gc();
System.gc();
// After
System.out.println("After:");
references.forEach(r -> {
System.out.println("Reference: " + r);
System.out.println("Object: " + r.get());
});
}
输出:
Before:
Reference: java.lang.ref.WeakReference@238e0d81
Object: java.lang.Object@31221be2
After:
Reference: java.lang.ref.WeakReference@238e0d81
Object: null
最好的方法可能是忽略get()
在"弹出"它们后返回null
条目。
旁注:我的第一个测试是使用字符串对象,它从未得到GC:ed。这是因为Java中的字符串是"暂留的"(见String.intern()
),这意味着有一个隐藏的静态字符串缓存被重用。一个字符串永远不会是GC:ed,除非该字符串池已满(或沿着该行的内容......我认为字符串是唯一具有这种"特殊"特征的 Java 对象,但我建议始终在 WeakReference 中使用自定义对象以确保它正确获得 GC:ed。