InterruptedException после открытия диалога открытия файла - 1.6.0_26
Выход из следующего кода:
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 GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Когда я запускаю программу, главное окно открывается нормально, и программа работает нормально.
Однако, если вы:
- откройте
JFileChooser
с помощью кнопки "Открыть файл"
- нажмите отменить, а затем
- выйти из программы
Выбрасывается An InterruptedException
. Или, если вы выберете файл и "Открыть", затем выйдите из программы, и будет сброшена одна и та же ошибка. На этом blog то же самое объясняется примером кода, его решение - как можно скорее вызвать new JFileChooser();
, что я сделал без эффекта.
Это ошибка в 1.6.0_26? Если да, то есть ли для этой версии обход?
Это код? Если да, то как это исправить? (С меньшей вероятностью, с двумя другими нулевыми результатами - один из которых теперь удален.)
Ответы
Ответ 1
Я бы сказал, что это небольшая ошибка в sun.awt.Disposer
.
Этот класс создает поток демона "Java2D Disposer", который обрабатывает ресурсы AWT собранных мусором объектов (в основном AWT-окна). Большую часть времени этот поток ожидает в своей ссылочной очереди для сбора нового одноразового объекта. Когда поток прерывается, он явно печатает это исключение.
Когда JVM завершается, он прерывает все потоки. В некоторых случаях, на которые, по-видимому, влияет использование JFileChooser и инициализированных им подсистем, некоторые потоки по-прежнему получают возможность запускать после этого прерывания. И в этом случае в поток "Java2D Disposer" бросается InterruptedException
, потому что он ожидал блокировки. Было бы лучше, если бы он проигнорировал это исключение во время выключения.
В качестве обходного решения замените
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);
}
});
Ответ 2
У меня была аналогичная проблема. Я исправил это, следуя советам
Ответ 3
Мой вывод для слегка измененной версии вашего источника (теперь включенного как редактирование самого вопроса) - это..
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
в выводе.
Ответ 4
Разница между кодом в блоге - это область JFileChooser. В блоге объект является локальной переменной в функции onClickedButton. В вашем примере объект определяется на уровне класса. Я предполагаю, что локальная переменная дает потоку Disposer больше времени для очистки объекта JFileChooser.
Когда я сделал объект выбора файла локальной переменной в блоке метода actionPerformed в вашем примере, исключение не произошло. Я тестировал его примерно десять раз. Оба запускают приложение через eclipse и через командную строку. Исключение не произошло.
Если исключение все еще происходит, вы можете инициализировать объект выбора файла в конструкторе GUI, но не присваивать его чему-либо. Я предполагаю, что он действует как ранняя инициализация и удаление тяжелого весового объекта.
Надеюсь, это поможет.
Ответ 5
Попробуйте добавить вызов System.gc()
, когда закончите с JFileChooser. У меня были проблемы с файловыми замками, которые этот вызов исправлен.