Java 弱hashmap是否会在其被取消引用后立即释放内存?
下面是将一些值放入WeakHashMap,然后从映射中删除这些值的代码片段。它如何处理分配的内存Java 弱hashmap是否会在其被取消引用后立即释放内存?,java,hashmap,Java,Hashmap,下面是将一些值放入WeakHashMap,然后从映射中删除这些值的代码片段。它如何处理分配的内存 import java.util.*; public class WeakHashMap_Main { private static Map map; public static void main(String args[]) { map = new WeakHashMap(); map.put(new String("ABC"), "XYZ");
import java.util.*;
public class WeakHashMap_Main {
private static Map map;
public static void main(String args[]) {
map = new WeakHashMap();
map.put(new String("ABC"), "XYZ");
map.put(new String("DEF"), "PQR");
map.remove("ABC");
map.remove("DEF");
}
}
内存在对象创建时分配给对象。任何数量的其他对象都可能引用该对象,从而引用其分配的内存 垃圾收集器是JVM的一个元素,它确定哪些对象仍然被引用(以及哪些对象是弱引用的)。它将不再引用的所有内存放回堆中,并准备再次使用。在任何情况下,如果内存足够低,等等,它也会将仅由弱引用引用的内存放回堆中,并对弱引用施展魔法,以便程序可以判断它们不再有效
因此,如果您将对对象的引用放在WeakHashMap中,然后将其取出,而这些是对这些对象的唯一引用,那么这些对象将不再被引用,并可用于垃圾收集。类
WeakHashMap
使用键的WeakReferences
。正常的HashMap
使用键的strong引用
垃圾收集由JVM自行管理。我们只能通过调用System.gc()
来影响JVM执行垃圾收集HashMap
防止密钥被垃圾收集WeakHashMap
不会阻止密钥被垃圾收集。如果存储在普通HashMap
中的密钥没有strong引用
,它将一直存储在HashMap
中,直到它被明确删除,之后密钥对象将有资格进行垃圾收集。但是,如果没有任何strong引用的密钥存储在WeakHashMap
中,它将有资格进行垃圾收集。一旦执行垃圾收集循环,密钥将被垃圾收集,然后该密钥对象上的contains
方法将返回false
在如下情况下,可释放WeakHashMap
使用的内存:
public static void main(String args[]) {
Map<String, String> map = new WeakHashMap<>();
String abc = "ABC";
String def = "DEF";
map.put(abc, "XYZ");
map.put(def, "PQR");
System.out.println(map.size()); // Guaranteed to be 2.
// Note: DO NOT remove the map entries!
// map.remove("ABC");
// map.remove("DEF");
// Allow the objects to be reclaimed
abc = null;
def = null;
// Do loads of memory-hungry operations here...
...
System.out.println(map.size()); // MAY POSSIBLY be 0 or 1. Or still 2.
}
publicstaticvoidmain(字符串参数[]){
Map Map=newweakhashmap();
字符串abc=“abc”;
字符串def=“def”;
地图放置(abc,“XYZ”);
地图放置(def,“PQR”);
System.out.println(map.size());//保证为2。
//注意:不要删除地图条目!
//地图。删除(“ABC”);
//地图。删除(“DEF”);
//允许回收对象
abc=null;
def=null;
//在这里执行大量内存不足的操作。。。
...
System.out.println(map.size());//可能是0或1,或者仍然是2。
}
这完全取决于垃圾收集器决定做什么(如果有的话)
这里的要点是,在添加两个条目之后,我们还没有触及地图。Java文档(jdk1.8.0_71)说
WeakHashMap
中的条目如果是键,将自动删除
已不再是普通用途。更准确地说,存在一个
给定密钥的映射不会阻止密钥被丢弃
通过垃圾收集器
这清楚地表明,当键
被丢弃时,其条目
也将从映射
中删除
现在,让我们看看发动机罩下面,看看当键被拔下时会发生什么。
remove(Object o)
方法的代码片段如下所示:
public V remove(Object key) {
Object k = maskNull(key);
int h = hash(k);
Entry<K,V>[] tab = getTable();
int i = indexFor(h, tab.length);
Entry<K,V> prev = tab[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (h == e.hash && eq(k, e.get())) {
modCount++;
size--;
if (prev == e)
tab[i] = next;
else
prev.next = next;
return e.value;
}
prev = e;
e = next;
}
return null;
}
Entry<K,V> e = tab[i];
tab[i] = new Entry<>(k, value, queue, h, e);
从代码片段可以看出,添加到WeakHashMap
的每个条目都将该条目存储在此队列中(在put(K,V)
操作期间调用构造函数如下所示:
public V remove(Object key) {
Object k = maskNull(key);
int h = hash(k);
Entry<K,V>[] tab = getTable();
int i = indexFor(h, tab.length);
Entry<K,V> prev = tab[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (h == e.hash && eq(k, e.get())) {
modCount++;
size--;
if (prev == e)
tab[i] = next;
else
prev.next = next;
return e.value;
}
prev = e;
e = next;
}
return null;
}
Entry<K,V> e = tab[i];
tab[i] = new Entry<>(k, value, queue, h, e);
条目e=tab[i];
tab[i]=新条目(k,值,队列,h,e);
)在删除操作期间,将从队列
中检索并删除相同的条目。此删除的条目的值设置为nulle.value=null
,稍后将GC'd。是的,它对GC没有任何控制权。这就是WeakHashMap
如何帮助丢弃带有键的映射值。释放内存是由垃圾收集器在必要时完成的。无法保证在任何特定时间释放内存;这取决于垃圾收集器的实现。通常,你不需要如此有力的保证。让GC完成它的工作,不用担心。现在大家都知道GC的功能了。我想知道一周散列图的特色。谢谢你的详细解释。。谁称之为expungeStaleEntries()?这是否像WeakHashMap上的任何操作都会调用此函数一样?我很高兴它对您的学习有所帮助expungestalentries()
是WeakHashMap
中的私有方法。它由private Entry[]getTable()
方法调用,就像我在前面的解释中提到的那样。每当在映射上调用remove(Object o)
方法时,remove()
方法依次调用此getTable()
,以获取有效的数组条目
。是否有理由不删除映射条目?我知道将键设为null是可行的,但我认为从WaelHashMap中删除kay值也有同样的效果。对吗?如果你想的话,你可以删除映射条目,但是如果你要这样做,你最好使用一个普通的HashMap。我的代码示例显示了WeakHashMap和HashMap之间的区别。非常感谢:)