I'm had some time on my lunch break today to work on one of the bugs I
selected for squishing before the release of OpenJUMP 01.00.02. Pedro
submitted this bug to the SourceForge tracker last May. Jon Aquino made some
comments, but the bug was never fixed. I believe a fix could be applied to
both JUMP and OpenJUMP.
Pedro received a ConcurrentModificationException from the
fireCategoryChanged() method of the LayerManager class. He said this
happened when "when you load a project with lots of layers and categories
and its behaviour is more or less random as to its occurrence."
Jon thought this could be fixed by wrapping the collection of LayerListeners
in an ArrayList.
I took a look at the LayerManager class and saw that the LayerListeners were
already stored in an instance of ArrayList, so I started looking for the
problem elsewhere. I noted that the fireLayerEvent() method which is called
by the fireCategoryChanged() method starts a new thread. I think this is
important because the Javadoc for the ConcurrentModificationException states
that: "For example, it is not generally permssible for one thread to modify
a Collection while another thread is iterating over it. In general, the
results of the iteration are undefined under these circumstances. Some
Iterator implementations (including those of all the collection
implementations provided by the JRE) may choose to throw this exception if
this behavior is detected. Iterators that do this are known as
*fail-fast*iterators, as they fail quickly and cleanly, rather that
risking arbitrary,
non-deterministic behavior at an undetermined time in the future."
I also noted that in Pedro's stack trace the LayerManager's addCategory()
method is called not once, but twice before the exception is thrown. When I
look at this and Pedro's description of what he was doing when he
encountered the exception I concluded that the following can happen in
OpenJUMP/JUMP.
The LayerManager.addCategory() method is called once. This method calls the
LayerManager.fireCategoryChanged() method, which in turn calls the
LayerManager.fireLayerEvent() method. The LayerManager.fireLayerEvent()
method creates a new thread and begins to iterate over the list calling
methods of the LayerListeners contained in the ArrayList.
While the thread that was created as a part of the first call to addCategory
is still executing, the second call to the LayerManager.addCategory()
occurs. This creates a second thread that attempts to manipulate the same
ArrayList that contains the LayerListeners.
I'm no expert at threads in Java, so I need some help determining the
solution. (I've got a book on Java threads that I tried to read over the
holiday break, but it started to give me a headache. I now I need to learn
more about threads, so I will return to the book soon.) I think I need to
create an class that extends ArrayList and makes the method to access
LayerListeners synchronized. Is this the way to fix the problem, or is there
a simpler solution?
The Sunburned Surveyor
(I knew bug squishing would be difficult, but why did my first one have to
involve threads.) :]
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel