据我了解,不应该对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;
}
}
答案 0 :(得分:3)
首先不要使用finalize
-已弃用,有更好的方法来清理自己,所以到处都是此类帖子(ReferenceQueue
和SoftReferences
)。
然后不要在WeakHashMap
中使用内部缓存为键的对象(String
就是这样)。
最后一点是,这与WeakHashMap
无关,这是对象的基本活泼性。在第一个示例中,您明确地将引用设置为null
,因此GC将其清除,而在第二个示例中,则不清除它们,并通过{{1 }};因此它不会被收集。
答案 1 :(得分:3)
在第一个示例中,将hashMap
变量设置为null
。这样就不再有对HashMap对象的引用,并且可以像任何其他类型的对象一样对其进行垃圾回收。 HashMap
和WeakHashMap
在这方面没有什么不同。
区别在于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上占主导地位。