JDK-8068244 : BasicDirectoryModel.cancelRunnables() throws ConcurrentModificationException
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 7u71,8u25,9,11,12
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_10
  • CPU: x86
  • Submitted: 2014-12-10
  • Updated: 2024-01-25
  • Resolved: 2020-09-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 16
16Resolved
Related Reports
Duplicate :  
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Redhat 6;  Linux 2.6.32-504.1.3.el6.x86_64 #1 SMP Fri Oct 31 11:37:10 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
The class javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread has a collection field called 'runnables' which has no synchronization or thread safety. This field is modified without any synchronization logic in the thread LoadFilesThread, but is looped over (without synchronization) when the public method cancelRunnables() is called (sometimes on the EventQueueThread, see stacktrace below). This leads to java.util.ConcurrentModificationException being thrown when certain race conditions are met (i.e. when it is modified and being looped over in separate threads, rare, but possible due to the fact that whenever JFileChooser.setCurrentDirection(...) is called it fires a property change on the EventQueue which can lead to Execptions if the LoadFilesThread makes a modification at the same time). 

Thread safety can be fixed by either adding synchronization blocks on the runnables field in the cancelRunnables(...) method/s and anywhere the runnables collection is modified OR modifying cancelRunnables(...) method to loop over an immutable COPY of the 'runnables' collection.

Below is the stack trace showing that a call to JFileChooser.setCurrentDirectory(...) on the EventQueueThread can lead to a ConcurrentModificationException because of the lack of thread safety in the javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread class.

java.util.ConcurrentModificationException
	at java.util.Vector$Itr.checkForComodification(Vector.java:1156)
	at java.util.Vector$Itr.next(Vector.java:1133)
	at javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:340)
	at javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:346)
	at javax.swing.plaf.basic.BasicDirectoryModel.validateFileCache(BasicDirectoryModel.java:135)
	at javax.swing.plaf.basic.BasicDirectoryModel.propertyChange(BasicDirectoryModel.java:69)
	at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
	at java.awt.Component.firePropertyChange(Component.java:8393)
	at javax.swing.JFileChooser.setCurrentDirectory(JFileChooser.java:581)
	at mtk.tools.api.ToolPathPanel.<init>(ToolPathPanel.java:73)
	at mtk.tools.api.ExtToolInfo$1.run(ExtToolInfo.java:57)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
	at java.awt.EventQueue.access$200(EventQueue.java:103)
	at java.awt.EventQueue$3.run(EventQueue.java:694)
	at java.awt.EventQueue$3.run(EventQueue.java:692)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
	at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect to NEVER get a ConcurrentModification being thrown in the BasicDirectoryModel class exception when calling JFileChooser.setCurrentDirectory() on the EventQueueThread.

I've only seen this exception once out of countless launches/uses of the application that produces the stack trace in the description, so this bug occurs rarely. But, it should never occur, and can be easily fixed. I don't think this is a bug in the application, since the stack trace shows that the swing call was done on the EDT (i.e. this is not an issue of initializing or performing operations on swing classes in background threads).
ACTUAL -
Rare occurrence of java.util.ConcurrentModificationException

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.util.ConcurrentModificationException
	at java.util.Vector$Itr.checkForComodification(Vector.java:1156)
	at java.util.Vector$Itr.next(Vector.java:1133)
	at javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:340)
	at javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:346)
	at javax.swing.plaf.basic.BasicDirectoryModel.validateFileCache(BasicDirectoryModel.java:135)
	at javax.swing.plaf.basic.BasicDirectoryModel.propertyChange(BasicDirectoryModel.java:69)
	at java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
	at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
	at java.awt.Component.firePropertyChange(Component.java:8393)
	at javax.swing.JFileChooser.setCurrentDirectory(JFileChooser.java:581)
	at mtk.tools.api.ToolPathPanel.<init>(ToolPathPanel.java:73)
	at mtk.tools.api.ExtToolInfo$1.run(ExtToolInfo.java:57)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
	at java.awt.EventQueue.access$200(EventQueue.java:103)
	at java.awt.EventQueue$3.run(EventQueue.java:694)
	at java.awt.EventQueue$3.run(EventQueue.java:692)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
	at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

REPRODUCIBILITY :
This bug can be reproduced rarely.


Comments
BasicDirectoryModel.FilesLoader thread is modified in JDK-8240690 to store and access "runnable" in COM thread for synchronization and also public method cancelRunnables() is modified to be private to restrict the access. Also, this issue is not seen in latest jdk/client jck run, so closing this as dup of JDK-8240690 which should be backported to 11u to avoid this issue.
25-09-2020

Probably a dup of JDK-8240690
31-08-2020