Bug 16304

Summary: ConcurrentModificationException
Product: JMeter Reporter: Chris <chrispesarchick>
Component: HTTPAssignee: JMeter issues mailing list <issues>
Status: RESOLVED FIXED    
Severity: major    
Priority: P3    
Version: 1.8   
Target Milestone: ---   
Hardware: PC   
OS: Linux   

Description Chris 2003-01-21 19:13:14 UTC
The problem seems to be the HashTree which is a HashMap.  This is a major
problem when there are multiple threads and the script is large.  If a thread
should get this error then the thread is done.  Then the test will not be
correct.  I tried a few things.   I tried synchronizing on the HashTree in
TestCompiler, but that didn't work. I then went to 'public void
traverse(HashTreeTraverser visitor)' in HashTree. I tried synchronizing on
list() and visitor that didn't work.  Then I created a static object and
synchronized the object and that has been working.  This slows down the
performance of setting up the test before it executes the test script.  Since I
don't have a full understanding of the program, my guess there is a better
place.  If anybody has another suggestion, let me know and I will give it a try.

This happens on NT and Linux.

java.util.ConcurrentModificationException
     at java.util.HashMap$HashIterator.nextEntry(HashMap.java:750)
     at java.util.HashMap$KeyIterator.next(HashMap.java:786)
     at

org.apache.jmeter.threads.TestCompiler.hasFunctions(TestCompiler.java:498)
     at

org.apache.jmeter.threads.TestCompiler.saveSamplerConfigs(TestCompiler.java:

 196)
     at

org.apache.jmeter.threads.TestCompiler.subtractNode(TestCompiler.java:158)
     at
 org.apache.jorphan.collections.HashTree.traverseInto(HashTree.java:908)
     at
 org.apache.jorphan.collections.HashTree.traverseInto(HashTree.java:902)
     at
 org.apache.jorphan.collections.HashTree.traverseInto(HashTree.java:902)
     at
 org.apache.jorphan.collections.HashTree.traverseInto(HashTree.java:902)
     at
org.apache.jorphan.collections.HashTree.traverse(HashTree.java:886)
     at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:125)
     at java.lang.Thread.run(Thread.java:536)
Comment 1 Mike Stover 2003-01-21 22:20:00 UTC
I just committed a change to org.apache.jmeter.testelement.AbstractTestElement
that changed the new HashMap() to Collections.synchronizedMap(new HashMap()).  I
think this should help fix this problem, and not slow things down overly much.

It's still not perfect, since to do a synchronized map correctly, you're
supposed to manually synchronize iteration code, but since the Map is a private
variable of AbstractTestElement, this is currently possible in other classes. 
One way to fix this would be to add a method to the TestElement interface, such as:

getSyncObject()

which would return the synchronized Map, so developers could write code such as:

Iterater iter = testElement.getPropertyNames().iterator();
synchronized(testElement.getSyncObject())
{
   while(iter.hasNext())
   {
      Object item = iter.next();
      //do stuff safely
   }
}

It seems inelegant to me, but I'm not sure what a good alternative is.  Using
Hashtable is not viable, since Map's can hold null values, and Hashtables can't,
and JMeter saves null values.
Comment 2 Chris 2003-02-24 20:43:19 UTC
I retried this with 1.8.1 and the problem is still there.