带有WeakHashMap keySet的java.lang.NegativeArraySizeException

时间:2015-03-31 22:28:35

标签: java dictionary arraylist

我有以下代码:

 public synchronized static ArrayList<HttpSession> getCurrentSessionList() {
      return new ArrayList<HttpSession>(sessions.keySet());
   }

我们有一个客户端获得java.lang.NegativeArraySizeException,其中列表使用地图sessions中的键值进行初始化。我无法复制它。他们在Linux上使用OpenJDK 7 build 71。

sessions是一个WeakHashMap,我假设是造成问题的原因。我知道创建一个新的List会创建一个对地图中项目的硬参考,但这是短暂的,只用于报告地图的内容。

创建ArrayList的原因是可以在循环等中操作项目,而不必担心WeakHashMap中的项目消失。

有人能建议一种安全的初始化方法吗?

1 个答案:

答案 0 :(得分:0)

听起来sessions是由WeakHashMap支持的同步地图。

JavaDoc for the ArrayList constructor being invoked说:

  

按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。

(强调添加。)因此,此构造函数遍历给定的集合。

JavaDoc for Collections.synchronizedMap()包含了这个非常重要的注释:

  

当迭代任何集合视图时,用户必须手动同步返回的地图:

Map m = Collections.synchronizedMap(new HashMap());
    ...
Set s = m.keySet();  // Needn't be in synchronized block
    ...
synchronized (m) {  // Synchronizing on m, not s!
    Iterator i = s.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
}
     

不遵循此建议可能会导致非确定性行为。

如果sessions确实是同步地图,则new ArrayList<HttpSession>(sessions.keySet())是非确定性的。您需要在sessions

上进行同步
public synchronized static ArrayList<HttpSession> getCurrentSessionList() {
    final Set<HttpSession> keys = sessions.keySet();
    synchronized (sessions) {
        return new ArrayList<HttpSession>(keys);
    }
}

..和getCurrentSessionList()静态方法可能不需要自己同步。