退出 Swing 应用程序时偶尔出现 InterruptedException [英] Occasional InterruptedException when quitting a Swing application

查看:24
本文介绍了退出 Swing 应用程序时偶尔出现 InterruptedException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I recently updated my computer to a more powerful one, with a quad-core hyperthreading processor (i7), thus plenty of real concurrency available. Now I'm occasionally getting the following error when quitting (System.exit(0)) an application (with a Swing GUI) that I'm developing:

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)

好吧,鉴于它开始发生在具有更强并发能力的硬件上,并且与线程有关,并且偶尔会发生,这显然是某种计时问题.但问题是堆栈跟踪太短了.我所拥有的只是上面的清单.它根本不包含我自己的代码,所以有点难以猜测错误在哪里.

Well, given that it started to happen with a more concurrency-capable hardware, and it has to do with threads, and it happens occasionally, it's obviously some kind of timing thing. But the problem is that the stack trace is so short. All I have is the listing above. It doesn't include my own code at all, so it's somewhat hard to guess where the bug is.

有没有人遇到过这样的事情?任何想法如何开始解决它?

Has anyone experienced something like this before? Any ideas how to start solving it?

由于使用 System.exit(0) 退出 Swing 应用程序可能不干净",但我不想将主框架设置为 EXIT_ON_CLOSE 因为我想确保在应用程序退出时没有任何重要的事情发生,所以我添加了一个机制,以便它在调用 之前执行主框架的 dispose() 方法System.exit(0).所以现在应该很干净了,但偶尔还是会发生异常.它发生在 System.exit(0) 被调用之后;dispose() 没有问题.也就是说,它必须来自关闭钩子:

Since quitting a Swing application with System.exit(0) may be "unclean", but I don't want to set the main frame to EXIT_ON_CLOSE because I want to ensure that there's nothing critical going on when the application quits, I added a mechanism so that it executes the main frame's dispose() method before calling System.exit(0). So it should be pretty clean now, but the occasional exception still happens. It happens after the System.exit(0) has been called; dispose() works with no problems. That is, it must be coming from a shutdown hook:

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.getWindows() 数组(它包含无所有者的 Dialog 等)来显式处理所有 Windows,但这并没有什么区别.这个问题似乎与清洁"(即在退出之前显式释放本机屏幕资源)关系不大.这是别的东西,但什么?

I even tried explicitly disposing all Windows by looping through Window.getWindows() array (it contains ownerless Dialogs and such), but it made no difference. This issue seems to have little to do with "cleanness" (i.e. explicitly releasing native screen resources before quitting). It's something else, but what?

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

Edit 2: Setting the default close operation to EXIT_ON_CLOSE made no difference. http://www.google.com/search?q=sun.java2d.Disposer.run(Disposer.java:125) finds a few bug reports, so maybe this indeed is a bug in Sun's Java2D implementation. I could imagine that bugs like this can go unfixed for a long time, because they're pretty harmless in practice; an exception from a shutdown hook hardly hurts anyone else. Given that this happens in a GUI app, the exception is not even noticed unless the stderr is directed to a console or log.

推荐答案

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

Your Disposer is blocked in a call to remove() (removing the next platform native resource). This means that the disposer thread (a daemon thread) is not being shutdown naturally when the VM exits (which you should expect since you are terminating it via System.exit()).

您的应用程序中有一个非守护进程线程,当您的所有摆动窗口都已被释放时,该线程会阻止 VM 退出.

You have a non-daemon thread in your application which is keeping the VM from exiting when all your swing windows have been disposed.

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

通常,如果所有的 Swing 窗口都被处理掉,swing 应用程序会正常退出,例如,此程序会弹出一个窗口,然后在关闭后退出(所有这些都没有调用 System.exit()):

Normally a swing application exits gracefully if all of its swing windows have been disposed of, for example, this program will pop a window then exit once it is closed (all with no call to System.exit()):

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

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

You might also try running the garbage collector before exiting, just for kicks.

这篇关于退出 Swing 应用程序时偶尔出现 InterruptedException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆