我有以下代码:
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中的项目消失。
有人能建议一种安全的初始化方法吗?
答案 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()静态方法可能不需要自己同步。