2

据我了解,HashMap 不应该被垃圾收集,WeakHashMap 应该被垃圾收集,但是当我运行这段代码时,hashmap 和weakhashmap 都被垃圾收集了。

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;
    }
}

输出:

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

仅使用 HashMap 时,GC 不会对其进行垃圾收集。

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;
    }
}

输出:

{a=hashmap}
4

4 回答 4

3

在您的第一个示例中,您将hashMap变量设置为null. 然后不再引用 HashMap 对象,它可以像任何其他类型的对象一样被垃圾收集。HashMap在这方面并WeakHashMap没有什么不同。

不同之处在于,当没有外部引用时,a 中的键可能会被垃圾回收WeakHashMap在正常情况HashMap下,这不会发生,因为地图本身包含对键的引用。

一旦收集了密钥,就WeakHashMap可以清除整个相应的条目。这个答案更详细地介绍了它。

于 2018-10-11T12:44:31.263 回答
3

首先不要使用finalize- 它已被弃用,有更好的方法来清理自己,SO 充满了这样的帖子(ReferenceQueue并且SoftReferences是其中之一)。

然后不要使用内部缓存的对象作为WeakHashMap( Stringis such) 中的键。

最后一点是,这与 无关WeakHashMap,这是对象的基本活力。在您的第一个示例中,您明确设置了对 的引用null,因此它们被 GC 清除,而在您的第二个示例中您没有,并通过System.out.println(hashMap);;保持对它的强引用。因此它不会被收集。

于 2018-10-11T12:43:13.537 回答
1

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

一句话:类的实例在不再被引用时被垃圾回收。它与类型无关。

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

此外,您正在调用 System.gc()... 您不能以编程方式调用 GC。它将按照自己的规则运行。充其量,您可以“建议”您希望 GC 运行的 JVM。

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

于 2018-10-11T12:40:12.203 回答
1

hashMap= null;您取消引用 HashMap 的对象的那一行。无论如何,在设置 null 后,在垃圾收集的下一个循环中,它将由垃圾收集器收集。

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

他们两者之间的区别:

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

于 2018-10-11T12:48:28.243 回答