Java HashMap与WeakHashMap一起被垃圾收集?

Java HashMap与WeakHashMap一起被垃圾收集?,java,collections,hashmap,garbage-collection,weakhashmap,Java,Collections,Hashmap,Garbage Collection,Weakhashmap,据我所知,HashMap不应该被垃圾收集,WeakHashMap应该被垃圾收集,但是当我运行这段代码时,HashMap和WeakHashMap都被垃圾收集。 import java.util.HashMap; import java.util.WeakHashMap; public class WeakHashMapDemo { public static void main(String[] args) { HashMap<String,Temp> hash

据我所知,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;
    }
}
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;
    }
}
仅使用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"));
        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;
    }
}
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;
    }
}

我想你误解了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"));
        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;
    }
}
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;
    }
}
这就是为什么关注变量的范围是如此重要。如果保留对不再需要的对象的引用,则不会收集该对象,并且会浪费资源

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


我建议你看一看:

首先不要使用
finalize
-它已经被弃用了,有更好的方法可以自己清理,因此到处都是这样的帖子(
ReferenceQueue
SoftReferences
就是其中之一)

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


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

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

不同之处在于,
WeakHashMap
中的密钥在没有外部引用时可能会被垃圾收集。在普通的
HashMap
中,这不会发生,因为映射本身包含对键的引用


收集钥匙后,WeakHashMap
可能会清除整个相应条目。详细介绍它。

在第
行hashMap=null取消引用HashMap的对象。在任何情况下,在设置null后,在垃圾收集的下一个周期,它将由垃圾收集器收集

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

两者的区别是:


WeakHashMap是Map接口的一个实现。WeakHashMap与HashMap几乎相同,但WeakHashMap的情况除外,如果将对象指定为不包含任何引用的键,则该对象可以进行垃圾收集,即使它与WeakHashMap关联。i、 垃圾收集器支配着WeakHashMap。

您在这里遇到了很多问题,使用被弃用的
finalize
(出于某种原因!)和使用
String
作为
WeakHashMap
的键,这又是另一个让人大吃一惊的地方。我真的不明白您想证明什么,在第二个示例中,您通过
System.out.println(hashMap)强烈引用了非null的
hashMap
-所以垃圾收集器绝对不能回收它;不像你的第一次example@Eugene好的,谢谢你的指点,但是在WeakHashMap中使用字符串不能对HashMap被垃圾收集负责。对吗?因为你把它设为null,明确地添加了一个答案来捕获这些评论。我认为您还应该解释在收集密钥后如何从
WeakHashMap
中清除条目…@Eugene这有点复杂,取决于实现,但我现在链接了另一个答案。