10

以下代码的输出是:

java.vendor     Sun Microsystems Inc.
java.version    1.6.0_26
java.runtime.version    1.6.0_26-b03
sun.arch.data.model     32
os.name     Windows XP
os.version  5.1
os.arch     x86
Input selection cancelled by user.
Exception while removing reference: java.lang.InterruptedException
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.ref.ReferenceQueue.remove(Unknown Source)
    at java.lang.ref.ReferenceQueue.remove(Unknown Source)
    at sun.java2d.Disposer.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

以下代码显示了我机器上的异常。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GUI extends JPanel implements ActionListener {

    private final String newline = System.getProperty("line.separator");
    JButton openButton;
    JTextArea log;
    JFileChooser fc;

    public GUI() {
        super(new BorderLayout());

        log = new JTextArea(20,40);
        log.setMargin(new Insets(5,5,5,5));
        log.setEditable(false);

        fc = new JFileChooser();

        openButton = new JButton("Open");
        openButton.addActionListener(this);

        JPanel buttonPanel = new JPanel(); //use FlowLayout
        buttonPanel.add(openButton);

        add(buttonPanel, BorderLayout.NORTH);
        add(new JScrollPane(log));

        showProp("java.vendor");
        showProp("java.version");
        showProp("java.runtime.version");
        showProp("sun.arch.data.model");
        showProp("os.name");
        showProp("os.version");
        showProp("os.arch");
    }

    public void showProp(String name) {
        output(name + " \t" + System.getProperty(name));
    }

    public void output(String msg) {
        log.append(msg + newline);
        log.setCaretPosition(log.getDocument().getLength());
        System.out.println(msg);
    }

    public void actionPerformed(ActionEvent e) {
        //Handle open button action.
        int returnVal = fc.showOpenDialog(GUI.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            //This is where a real application would open the file.
            output(
                "Input File Selected: " +
                fc.getSelectedFile().getName() +
                ".");

        } else {
            output("Input selection cancelled by user.");
        }
        log.setCaretPosition(log.getDocument().getLength());
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event dispatch thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("IDE Output Converter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Add content to the window.
        frame.add(new GUI());

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event dispatch thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

当我运行程序时,主窗口打开正常,程序运行正常。

但是,如果您:

  • 使用“打开JFileChooser文件”按钮打开
  • 按取消,然后
  • 退出程序

一个InterruptedException被抛出。或者,如果您选择一个文件并“打开”它然后退出程序,则会引发相同的错误。在这个博客上用示例代码解释了同样的事情,他的解决方案是尽快调用new JFileChooser();,我做了没有效果。

这是 1.6.0_26 中的错误吗?如果是这样,该版本是否有解决方法?

是代码吗?如果是这样,如何解决?(看起来不太可能,还有 2 个其他空结果 - 其中一个现在已被删除。)

4

5 回答 5

12

我会说这是sun.awt.Disposer.

该类创建“Java2D Disposer”守护线程,该线程处理垃圾收集对象(主要是 AWT 窗口)的 AWT 资源的处理。大多数情况下,该线程在其引用队列上等待新的一次性对象被垃圾回收。当线程被中断时,它会显式地打印该异常。

当 JVM 终止时,它会中断所有线程。在某些情况下——显然受到 JFileChooser 的使用和由它初始化的子系统的影响——一些线程在此中断后仍有机会运行。在这种情况下InterruptedException,“Java2D Disposer”线程中会抛出一个,因为它正在等待锁定。如果它在关机期间忽略该异常会更好。

作为一种解决方法,更换

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosed(WindowEvent e) {
        PrintStream nullStream = new PrintStream(new OutputStream() {
            public void write(int b) throws IOException {
            }

            public void write(byte b[]) throws IOException {
            }

            public void write(byte b[], int off, int len) throws IOException {
            }
        });
        System.setErr(nullStream);
        System.setOut(nullStream);
        System.exit(0);
    }
});
于 2011-10-26T09:53:27.563 回答
4

我有一个类似的问题。我按照这个线程的建议修复了它

于 2011-10-27T18:39:39.167 回答
2

我对您的源代码稍作修改的版本(现在作为对问题本身的编辑)的输出是..

java.vendor     Sun Microsystems Inc.
java.version    1.6.0_29
java.runtime.version    1.6.0_29-b11
sun.arch.data.model     32
os.name         Windows 7
os.version      6.1
os.arch         x86
Input File Selected: install.ini.
Input selection cancelled by user.
Press any key to continue . . .

从你的问题看来,重要的一行是:

Input selection cancelled by user.

但在那之后,我InterruptedException在输出中看不到任何内容。

于 2011-10-26T09:41:52.920 回答
0

System.gc()使用 JFileChooser 完成后尝试添加调用。我在此调用修复的文件锁定方面遇到了一些问题。

于 2011-10-27T11:02:33.600 回答
0

我在博文中看到的代码之间的区别在于JFileChooser的范围。在博客文章中,该对象是onClickedButton 函数中的一个局部变量。在您的示例中,对象是在类级别定义的。我假设作为一个局部变量给了 Disposer 线程更多的时间来清除 JFileChooser 对象。

在您的示例中,当我在 actionPerformed 方法块中将文件选择器对象设为局部变量时,没有发生异常。我确实测试了大约十次,都通过 eclipse 和命令行运行应用程序。没有发生异常。

如果异常仍然发生,您可以在 GUI 的构造函数中初始化文件选择器对象,但不要将其分配给任何对象。我在这里假设它作为一个重量级摆动对象的早期初始化和处置。

希望这可以帮助。

于 2011-10-27T10:39:15.580 回答