Search code examples
javaspring-mvcconcurrentmodification

ConcurrentModificationException on for loop on java.util.Set


This is may be duplicate question but I am a bit confuse in ConcurrentModificationException. I gone through some other questions on stack Overflow also some articles related to How to avoid ConcurrentModificationException. I come to know that this exception occurs while looping on collection AND modifying the same (most common issue with remove).

But in my case I am just looping (foreach) on an java.util.Set then am I m getting this exception.

Moreover I am not getting this exception always, When I do load testing of my web application using Jmeter (150 users in 5 seconds) in this scenario I m getting exception

Here is my code where I am getting exception according to stack trace from log file

public static Map<String, String> getMessageMap(Locale locale) {
    Properties properties;
    Set<Object> objkeys;
    Map<String, String> messageMap = null;

    if (messageMap == null) {
        messageMap = new HashMap<String, String>();
        // 1 Get properties file.
        properties = Utility.loadPropertiesFile(locale); // this method return properties from static veriable

        // 2 Get all keys of properties file.
        objkeys = properties.keySet();

        // 3 Add all key values into map.
        for (Object key : objkeys) { caught exception here
            String keyName = key.toString();
            if (keyName.contains("global.")) {
                messageMap.put(keyName, properties.getProperty(keyName));
            }
        }

    }
    return messageMap;
}

According to log file ConcurrentModificationException is occurred at line for (Object key : objkeys)

Here is some lines from stack trace

java.util.ConcurrentModificationException
at java.util.Hashtable$Enumerator.next(Unknown Source)
at com.utilities.MKCLUtility.getMessageMap(Utility.java:164)
at com.utilities.MKCLUtility.addMessage(Utility.java:49)
at com.controllers.LoginController.loginPost(LoginController.java:132)

What can I do to avoid this? and why this exception is occurring though I am not modifying the set.

Updated Code

Iterator<Object> iterator = objkeys.iterator();
while (iterator.hasNext()) 
{
    String keyName = iterator.next().toString();
    if (keyName.contains("global.")) {
        messageMap.put(keyName, properties.getProperty(keyName));
    }
}

Solution

  • By the guidance from comments on question I changed by code to :

        public static Map<String, String> getMessageMap(Locale locale) {
        Properties properties;
        Set<Object> objkeys;
    
    
        if (messageMap == null) {
            messageMap = new HashMap<String, String>();
            // 1 Get properties file.
            properties = MKCLUtility.loadPropertiesFile(locale);
    
            // 2 Get all keys of properties file.
            objkeys = properties.keySet();
    
            // 3 Add all key values into map.
            Iterator<Object> iterator = objkeys.iterator();
            while (iterator.hasNext()) 
            {
                String keyName = iterator.next().toString();
                if (keyName.contains("global.")) {
                    messageMap.put(keyName, properties.getProperty(keyName));
                }
            }
        }
        return messageMap;
    }
    

    I made messageMap as static so, this function on first request will check for null if it is null then messageMap get filled then for next request it will directly return messageMap.

    By this ConcurrentModificationException is resolved.

    But still If their some suggestion you want to give then Plzz I would like to know.