【问题标题】:Java hashmaps and memory leaksJava hashmaps 和内存泄漏
【发布时间】:2013-09-04 08:42:09
【问题描述】:

我有一个控制台 Java 应用程序,它需要来自数据库的一些数据。由于应用程序不断运行,每 30 秒一次,为了降低数据库的压力,我正在使用某种数据缓存。

因为数据库中没有大量需要的数据,所以我使用单例 Hashmap 作为我的缓存。我的缓存类如下所示:

public class Cache extends Hashmap<Integer, Hashmap<Integer, ArrayList<String>> {
//some code
}

系统每 5 分钟刷新一次缓存:

1) 为现有数据调用“clear()” 2) 用数据库中的新数据填充缓存。

告诉我,如果我为我拥有的结构(“嵌套”哈希图)调用“clear()”,Java 会清除我的缓存键下包含的所有数据,还是会导致内存泄漏?

【问题讨论】:

  • 简短回答:是的 clear() 完美运行。长答案(似乎是重复的):stackoverflow.com/questions/16231387/…
  • 释放映射中的键/值对象,但保留后备数组/表。
  • 听起来像是内存泄漏。您是否确保所有相关的 db 相关对象都没有引用您的 hashmap 中的项目? ...例如。 ResultSet

标签: java memory-leaks hashmap


【解决方案1】:

您可以这样做,但我建议更好的选择是替换它。如果您有多个线程,这将更有效。

public class Cache {
     private Map<Integer, Map<Integer, List<String>>> map;

     public Cache(args) {
     }

     public synchronized Map<Integer, Map<Integer, List<String>>> getMap() {
          return map;
     }

     // called by a thread every 30 seconds.
     public void updateCache() {
          Map<Integer, Map<Integer, List<String>>> newMap = ...
          // build new map, can take seconds.

          // quickly swap in the new map.
          synchronzied(this) {
              map = newMap;
          }
     }
}

这既是线程安全的,并且影响最小。

【讨论】:

  • 你在构建新地图时创建的地图是ConcurrentHashMap吗?似乎需要保证这个线程的安全。
  • 如果你同时阅读和写作,你只需要一个 ConcurrentMap。在这种情况下,它只是写入,并且在同步块之后,只有读取。不再需要锁/线程安全。
  • 啊,我看到您只在从数据库构建地图时写入地图,然后将其包装在 unmodifiableMap 中。但是,您不会将自己暴露在内存泄漏问题中吗?如果用户将getMap()返回的引用分配给某个变量,那么在updateCache之后它不会被GC。
  • 你不应该有任何getMap() 方法。使用封装原理,您想用地图隐藏确切的实现。缓存类应该有一些get(Integer key) 方法来访问数据。
  • @Xean +1,虽然它可能是 getList(int key1, int key2) 甚至是列表元素的访问者。
【解决方案2】:

这篇文章对你有帮助。

Is Java HashMap.clear() and remove() memory effective?

而且,HassMap 不是线程安全的。 如果要使用单例HashMap,最好使用ConcurrentHashMap。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 2015-08-14
    • 2012-08-11
    • 2015-12-14
    • 1970-01-01
    相关资源
    最近更新 更多