HashMap.remove和垃圾收集

时间:2015-04-02 10:03:15

标签: java garbage-collection hashmap

如果我将对象添加到HashMap,然后在不再需要它们时调用remove方法,它是否保证它们所采用的资源将被释放(假设没有其他参考) ?

6 个答案:

答案 0 :(得分:4)

如果您确定:

  

没有其他引用

是的,他们是候选人GC,这并不意味着他们会被中等地回忆!!。

你可以这样做:

System.gc();

但这不是一个好主意。有关详细信息,请查看thisthis个问题。

答案 1 :(得分:2)

HashMap个条目存储在一个数组中。如果删除条目,则相关的数组位置将为null。因此,hashMap已不再引用已删除的value对象。

然后,垃圾收集的常规规则将应用于value对象。

要验证的简单代码。

public class REPL7 {

    public static void main(String[] args) throws Exception {
        Map<String, Foo> map = new HashMap();
        map.put("one", new Foo("foo one"));
        map.put("two", new Foo("foo two"));

        // make the backing array accessible
        Field field = map.getClass().getDeclaredField("table");
        field.setAccessible(true);
        Object[] obj = (Object[]) field.get(map);

        // two references to Foo objects will be shown            
        System.out.println("obj = " + Arrays.toString(obj));

        map.remove("one");

        // only one reference to a Foo object will eb shown
        System.out.println("obj = " + Arrays.toString(obj));
    }
}

class Foo {
    String marker;

    Foo(String marker) {
        this.marker = marker;
    }

    @Override
    public String toString() {
        return "Foo{" + marker + '}';
    }
}

答案 2 :(得分:1)

不,因为您可能从其他地方引用该对象。

简单示例:

Map < int, Object > map = new HashMap < int, Object > ();
CustomObject x = new CustomObject();
map.put(1, x);
map.remove(1);
//you still have access to x

答案 3 :(得分:1)

垃圾收集总是在所有对象初始化的堆内存中完成。当您在remove中调用HashMap方法时,它只会删除其中的ID和值,而不是您创建的对象。

答案 4 :(得分:0)

如果Map是唯一引用Object的东西,并且您从Map中删除了Object引用,则是,不再从任何地方引用Object,并且它将符合GC的条件。一如既往,它所保留的资源将被保证释放,但无法确保何时会发生这种情况。

答案 5 :(得分:-1)

我将对象放在 HashMap 中,然后删除它们。

放置在HashMap中的对象的类:

public class ObjectTestsub {

    String name;
    
    public ObjectTestsub(String name) {
        this.name = name;
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("ObjectTestsub: " + name + " is garbage collected");
    }
}

主要内容:

public class ObjectTest {

    HashMap<String, ObjectTestsub> map;

    public static void main(String[] args) {

        var map = new HashMap<String, ObjectTestsub>();

        for (int i = 0; i < 1000000; i++) {
            map.put("Obj" + i, new ObjectTestsub("first " + i));
            map.remove("Obj" + i);
        }
    }
}

输出:

....
ObjectTestsub: first 822685 is garbage collected
ObjectTestsub: first 822684 is garbage collected
ObjectTestsub: first 822683 is garbage collected
ObjectTestsub: first 822682 is garbage collected
....
ObjectTestsub: first 822677 is garbage collected
ObjectTestsub: first 822676 is garbage collected
ObjectTestsub: first 822675 is garbage collected
ObjectTestsub: first 822674 is garbage collected

“销毁”的对象数量是 Java 垃圾收集器的问题。 这里相关的是收集了一些对象(因此已被释放)。 一切顺利。

现在我更改代码:

public class ObjectTest {

    HashMap<String, ObjectTestsub> map;

    public static void main(String[] args) {

        var map = new HashMap<String, ObjectTestsub>();

        for (int i = 0; i < 1000000; i++) {
            map.put("Obj" + i, new ObjectTestsub("first " + i));
        }
        System.out.println("first part has DONE!       size: " + map.size());
        
        for (int i = 0; i < 1000000; i++) {
            map.remove("Obj" + i);
        }
        System.out.println("second part has DONE!       size: " + map.size());
    }
}

这里的输出:

first part has DONE!       size: 1000000
second part has DONE!       size: 0

不再有来自“ObjectTestsub”对象的“析构函数”的消息。 好像还没有发布...

诀窍在哪里? :/