我们正在执行银行应用程序的负载测试/基准测试。当与大约100个虚拟用户一起运行时,我们将ConcurrentModificationException
作为错误之一。下面是stacktrace:
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:373)
at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:384)
at java.util.AbstractCollection.toArray(AbstractCollection.java:124)
at java.util.ArrayList.<init>(ArrayList.java:131)
at my.package.AuthorizationHelper.getAuthModuleList
以下是引起异常的getAuthModuleList()
部分:
private static final LinkedHashSet MODULE_SET = new LinkedHashSet();
public static List getAuthModuleList(..)
{
MODULE_SET.clear();
....
MODULE_SET.add(getAllrequiredModules());
List userLevelModules = getAllUserLevelModules();
if (userLevelModules != null) {
MODULE_SET.addAll(userLevelModules);
}
userLevelModules = new ArrayList(MODULE_SET); //Exception here
return userLevelModules;
}
模块需要首先按顺序执行,因此使用LinkedHashSet
。
以下是我对CME原因的理解:
MODULE_SET
。根据我的理解,如何修改代码以防止上述内容而不破坏功能:
更改此行:
userLevelModules = new ArrayList(MODULE_SET);
到此片段:
LinkedHashSet moduleSetCopy = new LinkedHashSet(MODULE_SET);
// userLevelModules = new ArrayList(MODULE_SET);
userLevelModules = new ArrayList(moduleSetCopy);
所以我的问题是,
请注意,该应用程序使用 Oracle JRockit(R)(构建R28.2.5-20-152429-1.6.0_37-20120927-1915-windows-x86_64,编译模式)而不是标准Sun JDK。我们需要模拟生产水平环境,因此不使用后者。
更新:不确定是否与回答相关,但在方法开始时会清除MODULE_SET
。
答案 0 :(得分:0)
哎呀,希望我的银行不会使用这个应用程序; - )
无论如何,您正在修改共享资源(MODULE_SET)而没有正确的同步或锁定,并且您的分析是正确的。但是,解决方案是,如果模块列表是用户或请求依赖的,则根本不使用共享资源,或者如果它是真正的单例,则初始化一次。
对于第一种选择,代码可能如下所示:
public static List getAuthModuleList(..)
{
LinkedHashSet MODULE_SET = new LinkedHashSet();
MODULE_SET.add(getAllrequiredModules());
List userLevelModules = getAllUserLevelModules();
if (userLevelModules != null) {
MODULE_SET.addAll(userLevelModules);
}
userLevelModules = new ArrayList(MODULE_SET); //Exception here
return userLevelModules;
}