【问题标题】:Why does a hashmap clear() free more memory than a pointer reassignment为什么 hashmap clear() 比指针重新分配释放更多的内存
【发布时间】:2013-07-12 14:00:15
【问题描述】:

我有一个包含十万个条目的新旧地图:

Map<State, CostAndIndex> oldMap = new LinkedHashMap<State, CostAndIndex>();
Map<State, CostAndIndex> newMap = new LinkedHashMap<State, CostAndIndex>();

在循环的每次迭代结束时,我只是这样做:

oldMap = newMap;

使用这种方法,我在一段时间后内存不足,即使在调用 System.gc(); 时也是如此。重新分配后。

然后我在重新分配之前添加了一个清除,我不再耗尽内存。

oldMap.clear();
oldMap = newMap;

我的问题:为什么它会改变什么?指针重新分配不是告诉 Java 不再需要地图及其内容,并且它可以清除数据并出于任何目的重用空间吗?

注意:这是运行 Java HotSpot 1.7。在 Java HotSpot 1.6 中,我用第一种方法更快地耗尽了内存,我也不清楚这是为什么。

【问题讨论】:

  • 不清楚您的代码到底是什么样的。如果您只曾经在循环之前初始化newMap,那么您只会得到一张可能会越来越大的地图。一个简短但完整的程序来演示这个问题会更容易解释......
  • 在对 map.clear() 的调用结束时,地图的内容将超出范围,无法访问并受 GC。然而,在重新分配期间,oldMap 仍然是范围可访问的(尽管没有对它的引用),并且直到for 循环结束之后才能进行 GC(我相信)。但是,鉴于@JonSkeet 在这里,我将继续前进并退出。
  • @ColinMorelli 请参阅我在答案中对我犯的愚蠢错误的评论。但是,我不清楚您的“oldMap 仍然是范围可访问的(尽管没有对它的引用),并且在 for 循环结束之前无法进行 GC”。你能扩展一下吗?

标签: java memory-management garbage-collection


【解决方案1】:

你是对的,它不应该在内存方面有任何区别 - 你必须有另一个对 oldMap 的引用,这会阻止它被 GC'd(如果 object1 和 object2 都指向 oldMap,并且您将 object1 更新为指向 newMap,然后 object2 仍将指向 oldMap,这将阻止它被 GC)

【讨论】:

  • 哦,我真傻。我刚刚意识到我的 CostAndIndex 仍然持有指向在上一次传递中计算的 State 对象的指针。这就是重新分配没有释放空间的原因:确实存在对 oldMap 中元素的引用,从而阻止了内存释放。
猜你喜欢
  • 2016-10-28
  • 1970-01-01
  • 2015-12-20
  • 1970-01-01
  • 2011-11-15
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多