3

I have the following code and just got ConcurrentModificationException.

fchProtocol = new FileChooser(lastFileLoc);
FileNameExtensionFilter xmlfilter = new FileNameExtensionFilter("xml files (*.xml)", "xml");
fchProtocol.setFileFilter(xmlfilter);  <<<< ***** exception from here

The exception trace info:

java.util.ConcurrentModificationException
    java.util.Vector$Itr.checkForComodification(Vector.java:1184)
    java.util.Vector$Itr.next(Vector.java:1137)
    javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:340)
    javax.swing.plaf.basic.BasicDirectoryModel$LoadFilesThread.cancelRunnables(BasicDirectoryModel.java:346)
    javax.swing.plaf.basic.BasicDirectoryModel.validateFileCache(BasicDirectoryModel.java:135)
    javax.swing.plaf.basic.BasicDirectoryModel.propertyChange(BasicDirectoryModel.java:69)
    java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:335)
    java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:327)
    java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:263)
    java.awt.Component.firePropertyChange(Component.java:8422)
    javax.swing.JFileChooser.setFileFilter(JFileChooser.java:1473)

This is the Java API method code. It is the last line throws the exception.

public void setFileFilter(FileFilter filter) {
        FileFilter oldValue = fileFilter;
        fileFilter = filter;
        if (filter != null) {
            if (isMultiSelectionEnabled() && selectedFiles != null && selectedFiles.length > 0) {
                Vector<File> fList = new Vector<File>();
                boolean failed = false;
                for (File file : selectedFiles) {
                    if (filter.accept(file)) {
                        fList.add(file);
                    } else {
                        failed = true;
                    }
                }
                if (failed) {
                    setSelectedFiles((fList.size() == 0) ? null : fList.toArray(new File[fList.size()]));
                }
            } else if (selectedFile != null && !filter.accept(selectedFile)) {
                setSelectedFile(null);
            }
        }
        firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
    }

This happened at GUI initialization stage. And the xmlfileter is a local variable.

I am using javaVersion = 1.8.0_20 in Linux. It is not reproducible and it only happened three times this year during my development process.

I don't know how to avoid this, or how to correctly use the FileChooser and its FileFilter. Anybody can help me?

EDIT:

It happened at the application initialization stage:

  1. main thread starts with main()
  2. initialized few non-GUI classes in the main thread;
  3. call

.

SwingUtilities.invokeAndWait(new Runnable()

    public void run()
    {    
         initalize GUI classes from here    
    }    
);

to do GUI initialization, but failed in that GUI initialization thread at the first few steps. There is NO other thread inside the GUI initialization thread. And also the main thread has no action to access the GUI initialization thread.

Basic at that moment there are two threads: the main thread and the GUI initialization thread started via invorkAndWait() call.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
peterboston
  • 877
  • 1
  • 12
  • 24
  • 2
    Can you post an [MCVE](http://stackoverflow.com/help/mcve)? I know you said this isn't reproducible, which is going to make it pretty hard to help. Are you doing anything with threads at all? – Kevin Workman May 20 '15 at 18:53
  • 3
    Perhaps https://bugs.openjdk.java.net/browse/JDK-8068244 – copeg May 20 '15 at 20:36
  • I have the impression that the stack trace is incomplete. Can you post a complete one? – geert3 May 20 '15 at 21:02
  • Yes, it is a complete one except the lines point to my code which I posted in the question: com.aaa.uiapp.common.bbb.ui.AbcPanel.createBottomControlBtnPanel(AbcPanel.java:791) – peterboston May 20 '15 at 21:31
  • I have also seen this happen once during `fileChooser.setFileView()`. The root cause seems to be the same JDK bug that @copeg linked to. So it seems to be a bug in `BasicDirectoryModel ` that can only be fixed by Oracle. At least it seems to happen rarely. – Enwired Sep 26 '16 at 17:47

2 Answers2

1

This kind of stuff happens all the time in Swing if you do GUI stuff on other threads than the Event Dispatch Thread. Especially the "not being reproducible" is a clue. It is a timing issue where concurrent threads are handling the GUI, whereas only the EDT should do that. See here for more info. So wrap GUI related things in SwingUtilities.invokeLater, in your case:

final FileFilter oldValue = fileFilter;
...
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
    }
});
geert3
  • 7,086
  • 1
  • 33
  • 49
  • That firePropertyChanged() method belongs to JAVA API. I cannot make any change on it. – peterboston May 20 '15 at 20:31
  • ok agreed. silly of me. but fact remains that both the not being reproducible and the concurrentmodificationexception hint towards your code interfering with the EDT. – geert3 May 20 '15 at 21:03
  • @peterboston invokeAndWait must be called out of EDT, you have to test for false from isEventDispatchThread, otherwise to use invoekLater (simple if-else) – mKorbel May 21 '15 at 05:45
0

Not really an answer but may prove useful to others hitting this question.

This is definitely a manifestation of https://bugs.openjdk.java.net/browse/JDK-8068244 from 2014. Just had it happen with Java 9.0.1/Windows 10, thrown on EDT in a JFrame constructor, very similar to what OP described.

java.util.ConcurrentModificationException
    at java.base/java.util.Vector$Itr.checkForComodification(Unknown Source)
    at java.base/java.util.Vector$Itr.next(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel$FilesLoader.cancelRunnables(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel$FilesLoader.cancelRunnables(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel.validateFileCache(Unknown Source)
    at java.desktop/javax.swing.plaf.basic.BasicDirectoryModel.propertyChange(Unknown Source)
    at java.desktop/java.beans.PropertyChangeSupport.fire(Unknown Source)
    at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
    at java.desktop/java.beans.PropertyChangeSupport.firePropertyChange(Unknown Source)
    at java.desktop/java.awt.Component.firePropertyChange(Unknown Source)
    at java.desktop/javax.swing.JFileChooser.setFileFilter(Unknown Source)
    at com.example.ExampleJFrame.initFileChoosers(Unknown Source)
    at com.example.ExampleJFrame.<init>(Unknown Source)
    at com.example.ExampleJFrame$15.run(Unknown Source)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.desktop/java.awt.EventQueue.access$500(Unknown Source)
    at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
    at java.desktop/java.awt.EventQueue$3.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

The code that causes it is properly executed on EDT via SwingUtilities.invokeLater() as evident in the stacktrace. The initFileChoosers() method only instantiates a couple of file choosers, calling setFileFilter() for them, sometimes multiple times in sequence.

Cannot be reproduced, of course.

predi
  • 5,528
  • 32
  • 60