退出Swing应用程序时偶尔会出现InterruptedException

Joo*_*kka 27 java concurrency multithreading java-2d interrupted-exception

我最近将我的计算机更新为更强大的计算机,配备了四核超线程处理器(i7),因此可以提供大量真正的并发性.现在我在退出()我正在开发的应用程序(使用Swing GUI)时偶尔会出现以下错误System.exit(0):

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)
Run Code Online (Sandbox Code Playgroud)

好吧,鉴于它开始发生在具有更多并发能力的硬件上,并且它与线程有关,并且它偶尔发生,它显然是某种时间性的东西.但问题是堆栈跟踪太短了.我只有上面的列表.它根本不包括我自己的代码,因此有点难以猜测bug的位置.

以前有没有经历过这样的事情?任何想法如何开始解决它?

编辑:因为退出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
Run Code Online (Sandbox Code Playgroud)

我甚至尝试Window通过循环遍历Window.getWindows()数组显式处理所有s (它包含无主Dialogs等),但它没有任何区别.这个问题似乎与"清洁度"(即在退出前明确释放本机屏幕资源)无关.这是别的什么,但是什么?

编辑2:设置默认关闭操作EXIT_ON_CLOSE没有区别.http://www.google.com/search?q=sun.java2d.Disposer.run(Disposer.java:125)发现了一些错误报告,所以这可能确实是Sun的Java2D实施中的一个错误.我可以想象像这样的虫子可以长时间不固定,因为它们在实践中是非常无害的; 关闭钩子的例外几乎不会伤害任何其他人.鉴于这种情况发生在GUI应用程序中,除非将stderr其定向到控制台或日志,否则甚至不会发现异常.

Jus*_*tin 15

您的Disposer在调用remove()时被阻止(删除下一个平台本机资源).这意味着当VM退出时,处理程序线程(守护程序线程)不会自然关闭(您应该期望通过System.exit()终止它).

您的应用程序中有一个非守护程序线程,当您所有的摆动窗口都被丢弃时,它会阻止VM退出.

解决方案:找到它并使其退出.

通常情况下,如果摆动窗口的所有摆动窗口都已被处理掉,它将正常退出,例如,该程序将弹出一个窗口,然后一旦关闭就退出(所有这些都没有调用System.exit()):

public static void main(String args[]) throws Exception {
    JFrame jf = new JFrame();
    jf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    jf.setVisible(true);
}
Run Code Online (Sandbox Code Playgroud)

您也可以在退出之前尝试运行垃圾收集器,只是为了踢.

  • 谢谢,查看调试器中的线程确实对这个问题有所了解。它似乎与一个名为“Swing-Shell”的线程有关,该线程由 JFileChooser 创建。事实上,当我不打开 JFileChooser 时,应用程序永远不会在关闭时崩溃。Sun 错误 6744953、6741890 和 6713352 确实报告了该线程的一些问题。如果我能够提出可重现的演示案例,我将进一步调查并提交错误报告。 (2认同)

小智 5

如果您使用的是 Swing 应用程序,则首先调用 System.gc(),然后调用 dispose() 方法。我认为它会工作得很好..我也用这个。

想对此进行投票,但我需要更多代表。这个解决方案对我有用,尽管我找不到原因的解释,我的同事也说这没有意义。

我有 1.7 和我创建的 Swing 应用程序,它读入一个文件,重新排列内容,然后输出到一个文件。有一个运行和退出按钮。使用首选项 API、作者、读者和其他一些东西。在立即打开和关闭应用程序(没有System.gc())时,只有连续两次将返回与上述相同的异常。但System.gc()就在dispose()我无法再次抛出异常之前。