How to avoid ConcurrentModificationException from JFileChooser.setFileFilter () call?

I have the following code and just got a ConcurrentModificationException.

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

      

Exception trace information:

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. This last line throws an 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 during the GUI initialization phase. And xmlfileter is a local variable.

I am using javaVersion = 1.8.0_20 on Linux. This is not reproducible and has only happened three times this year during my development process.

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

EDIT:

This happened during the initialization phase of the application:

  • The main theme starts with main ()
  • initialized several classes without GUI in the main thread;
  • call

...

SwingUtilities.invokeAndWait(new Runnable()

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

      

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

Basically there are two threads at this point: the main thread and the GUI initialization thread launched by invorkAndWait () call.

+3


source to share


2 answers


This kind of thing happens all the time in Swing if you are making GUI files on threads other than Thread Dispatch Thread. Especially "non-reproducibility" is the key. This is a timing issue where parallel threads are processing the GUI whereas EDT only has to do it. See here for details . So bring the GUI-related stuff into SwingUtilities.invokeLater

, in your case:



final FileFilter oldValue = fileFilter;
...
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        firePropertyChange(FILE_FILTER_CHANGED_PROPERTY, oldValue, fileFilter);
    }
});

      

+1


source


Not really an answer, but might be helpful to others addressing this question.

It is definitely a manifestation of https://bugs.openjdk.java.net/browse/JDK-8068244 from 2014. Only if it happened with Java 9.0.1 / Windows 10, EDT in JFrame constructor very similar to the one described by OP.

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 calls it is executed correctly on the EDT using SwingUtilities.invokeLater()

, as seen in the stacktrace. The method initFileChoosers()

creates only a few files by calling setFileFilter()

on them, sometimes multiple times in sequence.

Impossible to reproduce, of course.

0


source







All Articles