如何避免来自JFileChooser.setFileFilter()调用的ConcurrentModificationException?

时间:2015-05-20 18:46:35

标签: java swing jfilechooser concurrentmodification

我有以下代码,只是得到了ConcurrentModificationException。

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

异常跟踪信息:

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)

这是Java API方法代码。这是最后一行抛出异常。

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);
    }

这发生在GUI初始化阶段。 xmlfileter 是一个局部变量。

我在Linux中使用 javaVersion = 1.8.0_20 。它不可重复,在我的开发过程中今年只发生了三次。

我不知道如何避免这种情况,或者如何正确使用FileChooser及其FileFilter。有人可以帮帮我吗?

修改

它发生在应用程序初始化阶段:

  1. 主线程以main()
  2. 开头
  3. 在主线程中初始化了几个非GUI类;
  4. 致电
  5. SwingUtilities.invokeAndWait(new Runnable()
    
        public void run()
        {    
             initalize GUI classes from here    
        }    
    );
    

    进行GUI初始化,但在最初的几个步骤中,GUI初始化线程失败了。 GUI初始化线程中没有其他线程。而且主线程也无法访问GUI初始化线程。

    基本时刻有两个线程:主线程和GUI初始化线程通过invorkAndWait()调用启动。

2 个答案:

答案 0 :(得分:1)

如果你在事件调度线程之外的其他线程上执行GUI工作,这种事情一直在Swing中发生。特别是&#34;不可重现&#34;是一个线索。并发线程正在处理GUI是一个时间问题,而只有EDT应该这样做。有关详细信息,请参阅here。 因此,在您的情况下,在SwingUtilities.invokeLater中包装与GUI相关的内容:

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

答案 1 :(得分:0)

不是一个真正的答案,但可能对其他人提出这个问题很有用。

这绝对是2014年https://bugs.openjdk.java.net/browse/JDK-8068244的一种表现。只是在Java 9.0.1 / Windows 10中发生,在JFrame构造函数中抛出EDT,与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)

导致它的代码在EDT上通过SwingUtilities.invokeLater()正确执行,如堆栈跟踪中所示。 initFileChoosers()方法仅实例化几个文件选择器,为它们调用setFileFilter(),有时按顺序多次调用。

当然不能复制。