We are performing a load testing / benchmark of a banking application. We are getting ConcurrentModificationException
as one of the errors when running with around 100 virtual users. Below is the 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
Below is the section in getAuthModuleList()
which is causing the exception:
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;
}
Modules need to be executed in order with required ones first, hence using LinkedHashSet
.
Following is my understanding of the cause for the CME:
MODULE_SET
. How the code should be modified to prevent the above without breaking functionality as per my understanding:
Change this line:
userLevelModules = new ArrayList(MODULE_SET);
To this snippet:
LinkedHashSet moduleSetCopy = new LinkedHashSet(MODULE_SET);
// userLevelModules = new ArrayList(MODULE_SET);
userLevelModules = new ArrayList(moduleSetCopy);
So my questions are,
Note that the application uses Oracle JRockit(R) (build R28.2.5-20-152429-1.6.0_37-20120927-1915-windows-x86_64, compiled mode) and not the standard Sun JDK. We need to simulate production level environment hence not using the latter.
UPDATE : Not sure if relevant to answering, but MODULE_SET
is being cleared at the start of the method.
Ouch, hopefully it is not my bank that is going to use this application ;-)
Anyway, you are modifying a shared resource (MODULE_SET) without proper synchronization or locks, and yor analysis is correct. The solution, however, is to not use the shared resource at all if the list of modules is user or request dependent, or initialize it once if it is a true singleton.
For the first alternative, the code could look like this:
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;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.