Случайное InterruptedException при выходе из приложения Swing - PullRequest
27 голосов
/ 20 мая 2010

Я недавно обновил свой компьютер до более мощного, с четырехъядерным процессором Hyper-Threading (i7), таким образом, было много реального параллелизма. Теперь я иногда получаю следующую ошибку при выходе (System.exit(0)) из приложения (с графическим интерфейсом Swing), которое я разрабатываю:

Exception while removing reference: java.lang.InterruptedException
java.lang.InterruptedException
        at java.lang.Object.wait(Native Method)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
        at sun.java2d.Disposer.run(Disposer.java:125)
        at java.lang.Thread.run(Thread.java:619)

Что ж, учитывая, что это начало происходить с аппаратным обеспечением с более высокой степенью параллелизма, оно имеет отношение к потокам, и иногда это происходит, очевидно, это какая-то временная вещь. Но проблема в том, что трассировка стека такая короткая. Все, что у меня есть, это список выше. Он вообще не включает в себя мой собственный код, поэтому довольно сложно догадаться, где ошибка.

Кто-нибудь испытывал что-то подобное раньше? Есть идеи, как начать ее решать?

Редактировать: Поскольку выход из приложения Swing с System.exit(0) может быть «нечистым», но я не хочу устанавливать основной фрейм на EXIT_ON_CLOSE, потому что я хочу убедиться, что ничего критического продолжая работу при выходе из приложения, я добавил механизм, чтобы он выполнял метод dispose() основного фрейма перед вызовом System.exit(0). Так что теперь это должно быть довольно чисто, но случайное исключение все же случается. Это происходит после того, как System.exit(0) был вызван; dispose() работает без проблем. То есть, это должно происходить от отключающего крюка:

mainFrame.dispose(); // No problem! After this returns, all visible GUI is gone.
// In fact, if there were no other threads around, the VM could terminate here.
System.exit(0); // Throws an InterruptedException from sun.java2d.Disposer.run

Я даже пытался явно удалить все Window s, просматривая массив Window.getWindows() (он содержит Dialog s без владельца и тому подобное), но это не имело никакого значения. Эта проблема, похоже, не имеет ничего общего с «чистотой» (то есть явным освобождением ресурсов собственного экрана перед выходом). Это что-то еще, но что?

Редактировать 2: Установка операции закрытия по умолчанию на EXIT_ON_CLOSE не изменила. http://www.google.com/search?q=sun.java2d.Disposer.run(Disposer.java:125) находит несколько отчетов об ошибках, так что, возможно, это действительно ошибка в реализации Sun Java2D. Я мог бы предположить, что подобные ошибки могут оставаться незафиксированными в течение длительного времени, потому что они довольно безопасны на практике; исключение из крюка отключения вряд ли повредит кому-либо еще. Учитывая, что это происходит в приложении с графическим интерфейсом, исключение даже не замечается, если stderr не направлен на консоль или журнал.

Ответы [ 17 ]

0 голосов
/ 06 ноября 2012

Попробуйте использовать EventQueue.invokeLater () , чтобы закрыть ваш Swing.

0 голосов
/ 03 мая 2012

Если вы используете приложение Swing, сначала вызовите System.gc (), а затем вызовите метод dispose (). Я думаю, что это будет работать нормально .. Я также использую это.

0 голосов
/ 28 мая 2010

Потоки в java заканчиваются, только когда все методы run () заканчивают выполнение. Иначе у вас всегда будут эти расширенные объекты Thread в VM. Вы должны закончить все темы перед выходом из приложения.

Также учтите, что когда вы создаете jFrame, вы запускаете тему (CURRENT_THREAD, я считаю)

0 голосов
/ 28 мая 2010

Если вы используете Swing App Framework , вы можете переопределить Application.exit() для выполнения очистки или добавить ExitListener. В противном случае вы также можете добавить в свое приложение кнопку отключения Runtime.getRuntime().addShutdownHook().

0 голосов
/ 11 апреля 2014

Я только что столкнулся с этой ошибкой при использовании баз данных. Проблема заключалась в том, что соединение с базой данных не было закрыто. Я решил это с помощью следующего кода:

Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    });

Просто выбросить это для других людей ...

0 голосов
/ 11 ноября 2014

Попробуй это. Это сработало для меня. Я создавал экземпляр JFileChooser, который не был правильно удален после вызова System.exit (0).

setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent ev) {                	
                dispose();
                System.exit(0);
                }
 });
0 голосов
/ 16 августа 2011

Я получил похожую ошибку, и почему-то это сработало для меня:

private static void createAndShowGUI() {
  JFrame jf = new MyProgram();
  jf.setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        public void run() {
          createAndShowGUI();
        }
    });
}
...