我最近把电脑升级成了一台更加强大的机器,它拥有一个四核超线程处理器(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)
显然,由于它开始在更具并发性能的硬件上出现,并且涉及线程,并且偶尔发生,所以这显然是某种计时问题。但问题在于堆栈跟踪非常简短。我只有上面的列表。它根本没有包括我的代码,因此很难猜测错误在哪里。
有人遇到过类似的情况吗?有什么想法可以开始解决吗?
编辑:由于使用 System.exit(0)
退出 Swing 应用程序可能会导致 "不干净",但我不想将主框架设置为 EXIT_ON_CLOSE
,因为我希望确保应用程序退出时没有任何关键操作正在进行,因此我添加了一个机制,在调用 System.exit(0)
之前执行主框架的 dispose()
方法。所以现在应该很干净了,但偶尔还是会出现异常。这发生在调用 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.getWindows()
数组(其中包含没有所有者的Dialog
等)显式地处理所有Window
,但并没有什么区别。这个问题似乎与“cleanliness”(即在退出之前显式释放本机屏幕资源)关系不大。它是其他一些原因,但是什么原因呢?
编辑2:将默认关闭操作设置为EXIT_ON_CLOSE
没有任何区别。在http://www.google.com/search?q=sun.java2d.Disposer.run(Disposer.java:125)上找到了一些错误报告,因此可能确实是Sun的Java2D实现中的一个错误。我可以想象,像这样的错误可能会长时间未被修复,因为它们在实践中相当无害;来自关闭挂钩的异常几乎不会伤害任何其他人。鉴于这发生在GUI应用程序中,除非将stderr
定向到控制台或日志,否则甚至不会注意到异常。