偶尔中断退出 Swing 应用程序时的异常

我最近将我的计算机更新为功能更强大的计算机,具有四核超线程处理器(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)

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

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

编辑:由于退出 Swing 应用程序可能是“不干净的”,但我不想将主框架设置为,因为我想确保在应用程序退出时没有任何关键发生,所以我添加了一个机制,以便它在调用之前执行主框架的方法。所以它现在应该很干净,但偶尔的例外仍然会发生。它发生在调用之后; 没有问题。也就是说,它必须来自关机挂钩:System.exit(0)EXIT_ON_CLOSEdispose()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

我甚至尝试通过循环数组(它包含无所有者的s等)显式地释放所有s,但它没有任何区别。这个问题似乎与“清洁”(即在退出之前明确释放本机屏幕资源)关系不大。这是别的东西,但是什么?WindowWindow.getWindows()Dialog

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


答案 1

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

应用程序中有一个非守护程序线程,当所有 Swing 窗口都已释放时,该线程可防止 VM 退出。

解决方案:找到它并让它退出。

通常,如果一个 swing 应用程序的所有 Swing 窗口都已释放,则会优雅地退出,例如,此程序将弹出一个窗口,然后在关闭后退出(所有窗口都不调用 System.exit()):

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

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


答案 2

如果您使用的是 swing 应用程序,请先调用 System.gc(), 然后调用 dispose() 方法。我认为它会正常工作。我也使用这个。

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

我有1.7和我创建的swing应用程序,它可以读取文件,重新排列内容,然后输出到文件。有一个运行和退出按钮。使用首选项API,编写器,读取器和其他一些东西。打开和关闭应用程序(不带)后,立即仅连续两次将返回上述相同的异常。但是在我之前,我无法让异常再次抛出。System.gc()System.gc()dispose()


推荐