此HashMap的内存泄漏在哪里?

时间:2019-06-21 11:18:30

标签: java memory-leaks hashmap

我需要确定此代码中的内存泄漏在哪里

我不知道该怎么做

我怀疑HashMap在获取新资源时会发生内存泄漏,但我不太确定

public class Runner {
    private HashMap<Integer, Resource> resources = new HashMap<Integer, Resource>();

    public Iterable<Resource> getResources() {
        return this.resources.values();
    }

    public Resource acquireResource(int id) {
        Resource w = this.resources.get(id);
        if (w == null) {
            w = new Resource(id);
            this.resources.put(id, w);
        }

        return w;
    }

    public void releaseResource(int id) {
        Resource w = this.resources.getOrDefault(id, null);
        if (w == null)
            throw new IllegalArgumentException();

        w.dispose();
    }

    public static void main(String[] args) {
        Runner d = new Runner();

        d.acquireResource(1).performTask("Task11");
        d.acquireResource(2).performTask("Task21");
        System.out.println(String.join(", ", d.acquireResource(2).getTasks()));
        d.releaseResource(2);
        d.acquireResource(1).performTask("Task12");
        System.out.println(String.join(", ", d.acquireResource(1).getTasks()));
        d.releaseResource(1);
    }

    public class Resource {
        private ArrayList<String> tasks = new ArrayList<String>();

        private int id;

        public int getId() {
            return this.id;
        }

        public Iterable<String> getTasks() {
            return this.tasks;
        }

        public Resource(int id) {
            this.id = id;
        }

        public void performTask(String task) {
            if (this.tasks == null)
                throw new IllegalStateException(this.getClass().getName());

            this.tasks.add(task);
        }

        public void dispose() {
            this.tasks = null;
        }
    }
}

内存泄漏,我不知道什么

2 个答案:

答案 0 :(得分:4)

您没有从地图中删除任何条目,因此理论上它可能会不断增长。您可能应该调用resources.remove(id)而不是resources.getOrDefault(id, null),因为前者实际上删除了条目,而后者没有删除。

答案 1 :(得分:1)

您不会释放您获得的所有资源。让我们检查一下您共享的main

d.acquireResource(1).performTask("Task11");
d.acquireResource(2).performTask("Task21");
System.out.println(String.join(", ", d.acquireResource(2).getTasks()));
d.releaseResource(2);

// 1 is acquired again, without relesaing the first 1 you acquired
d.acquireResource(1).performTask("Task12");
System.out.println(String.join(", ", d.acquireResource(1).getTasks()));
d.releaseResource(1);