HashMap与WeakHashMap一起被垃圾回收了吗?

时间:2018-10-11 12:23:06

标签: java collections hashmap garbage-collection weakhashmap

据我了解,不应该对HashMap进行垃圾回收,而WeakHashMap应当进行垃圾回收,但是当我运行此代码时,将同时对hashmap和weakhashmap进行垃圾回收。

composer dumpautoload

输出:

import java.util.HashMap;
import java.util.WeakHashMap;
public class WeakHashMapDemo {
    public static void main(String[] args) {
        HashMap<String,Temp> hashMap= new HashMap<>();
        hashMap.put("a", new Temp("hashmap"));
        WeakHashMap<String,Temp> weakHashMap= new WeakHashMap<>();
        weakHashMap.put("a", new Temp("identity hashmap"));
        hashMap= null;
        weakHashMap= null;
        System.gc();
        try {
            Thread.sleep(5000);
        }catch(InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        }
        System.out.println(hashMap);
        System.out.println(weakHashMap);
    }
}
class Temp {
    String name;
    Temp(String name) {
        this.name= name;
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println(name+":: Finalize Method Executed");
    }
    @Override
    public String toString() {
        return this.name;
    }
}

虽然仅使用HashMap,但GC并没有对其进行垃圾收集。

identity hashmap:: Finalize Method Executed
hashmap:: Finalize Method Executed
null
null

输出:

import java.util.HashMap;
import java.util.WeakHashMap;
public class WeakHashMapDemo {
    public static void main(String[] args) {
        HashMap<String,Temp> hashMap= new HashMap<>();
        hashMap.put("a", new Temp("hashmap"));
        System.gc();
        try {
            Thread.sleep(5000);
        }catch(InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        }
        System.out.println(hashMap);
    }
}
class Temp {
    String name;
    Temp(String name) {
        this.name= name;
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println(name+":: Finalize Method Executed");
    }
    @Override
    public String toString() {
        return this.name;
    }
}

4 个答案:

答案 0 :(得分:3)

首先不要使用finalize-已弃用,有更好的方法来清理自己,所以到处都是此类帖子(ReferenceQueueSoftReferences )。

然后不要在WeakHashMap中使用内部缓存为键的对象(String就是这样)。

最后一点是,这与WeakHashMap无关,这是对象的基本活泼性。在第一个示例中,您明确地将引用设置为null,因此GC将其清除,而在第二个示例中,则不清除它们,并通过{{1 }};因此它不会被收集。

答案 1 :(得分:3)

在第一个示例中,将hashMap变量设置为null。这样就不再有对HashMap对象的引用,并且可以像任何其他类型的对象一样对其进行垃圾回收。 HashMapWeakHashMap在这方面没有什么不同。

区别在于WeakHashMap中的在没有外部引用的情况下可能会被垃圾回收。在普通的HashMap中,不会发生这种情况,因为地图本身保存了对键的引用。

一旦收集了密钥,WeakHashMap可能会清除整个对应的条目。 this answer对此有更详细的说明。

答案 2 :(得分:1)

我认为您误解了GC的工作原理。

一句话:当不再引用类实例时,将对其进行垃圾回收。 与类型无关。

这就是为什么要注意变量的范围如此重要的原因。如果您保留对不再需要的对象的引用,则该对象将不会被收集并且会浪费资源。

此外,您正在调用System.gc()...您无法以编程方式调用GC。它将根据自己的规则运行。充其量,您可以“建议”您要运行GC的JVM。

我建议您看看:https://www.dynatrace.com/resources/ebooks/javabook/how-garbage-collection-works/

答案 3 :(得分:1)

hashMap= null;行,您取消了HashMap对象的引用。无论如何,将其设置为null后,在下一个垃圾收集周期中,垃圾收集器都会收集该垃圾。

在第二种情况下,您并没有将hashMap设置为null。

它们之间的区别:

WeakHashMap是Map接口的实现。 WeakHashMap与HashMap几乎相同,除了在WeakHashMap的情况下,如果将对象指定为键不包含任何引用-即使它与WeakHashMap关联,也可以进行垃圾回收。即垃圾收集器在WeakHashMap上占主导地位。