我正在尝试使用LinkedHashMap作为本地FIFO缓存解决方案,覆盖其removeEldestEntry方法以保持大小固定:
Map lhm = new LinkedHashMap(MAX_CACHE_SIZE + 1, .75F, false) {
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_CACHE_SIZE;
}
};
但是当我不断向地图监控进程内存添加新条目时,我发现它一直在增长,直到使用最大虚拟机内存,但地图大小不会增加。
是否按设计?如果丢弃旧值并且地图的大小有限,为什么需要更多内存呢?
更新: 根据要求,我附上完整的代码:
@Test
public void mapMemory() {
final int MAX_CACHE_SIZE = (int) 1E3;
Map lhm = new LinkedHashMap(MAX_CACHE_SIZE + 1, 1F, false) {
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_CACHE_SIZE;
}
};
for (long i = 0; i < 1E10; i++) {
lhm.put("key_" + i, "VALUE");
}
}
答案 0 :(得分:2)
在多线程上下文中解释LinkedHashMap的内存泄漏问题的博客文章
https://hoangx281283.wordpress.com/2012/11/18/wrong-use-of-linkedhashmap-causes-memory-leak/
答案 1 :(得分:0)
构造函数中的第二个参数定义了loadFactor,乘以第一个参数(地图大小),它会为您提供触发调整大小的值(大小)。所以在你的情况下你应该(可能)使用loadFactor = 1。
编辑:
您的内存泄漏是由您未向我们展示的内容引起的,您上面的代码绝不会导致内存泄漏
检查您可能保留对旧值/对象的引用的位置。映射本身不会导致内存泄漏 - 如果它确实所有使用映射的系统(并且有很多它们)将每隔几个小时崩溃。
答案 2 :(得分:0)
如果您需要随机访问集合的内容,那么它实际上不是FIFO。
应该注意的是,集合不存储对象,它们存储对象的引用,这是一个重要的区别。将相同的对象存储在2个不同的集合中将不会产生大量的内存开销,因此最好的解决方案是将相同的对象存储到队列和映射中,当需要FIFO行为时使用队列,当需要随机访问时使用Map 。
您必须记住在完成它时从两个集合中删除该对象,否则它将不会是GC。