【问题标题】:HashMap being garbage collected along with WeakHashMap?HashMap 与 WeakHashMap 一起被垃圾收集?
【发布时间】:2018-10-11 12:23:05
【问题描述】:

据我了解,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}

【问题讨论】:

  • 这里有很多问题,使用已弃用的finalize(出于某种原因!)并使用String 作为WeakHashMap 中的键 - 这又是一个大惊喜跨度>
  • 我真的不明白你想在这里证明什么,在你的第二个例子中,你通过System.out.println(hashMap); 强烈引用了非空hashMap - 所以垃圾收集器绝对不能收回它;不像你的第一个例子
  • @Eugene 好的,感谢您的指点,但在 WeakHashMap 中使用字符串不能负责 HashMap 被垃圾收集......对吗?
  • 因为您明确地将其设置为 null
  • 添加了捕获这些 cmets 的答案

标签: java collections hashmap garbage-collection weakhashmap


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    一旦收集到密钥,WeakHashMap 可能会清除整个相应条目。 this answer 详细介绍了它。

    【讨论】:

    • 我认为您还应该解释在收集到密钥后如何从WeakHashMap 清除条目...
    • @Eugene 这有点复杂且依赖于实现,但我现在已经链接了另一个 SO 答案。
    【解决方案3】:

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

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

      两者的区别:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-21
        • 1970-01-01
        • 2011-09-30
        • 2015-04-09
        • 1970-01-01
        • 1970-01-01
        • 2017-11-03
        • 1970-01-01
        相关资源
        最近更新 更多