在AWT队列线程中调试异常

时间:2014-12-22 13:07:01

标签: java scala debugging intellij-idea awt

我正在开发一个Swing应用程序,其中包含一个执行自定义绘制的组件。当我在绘制代码中犯了一些错误并抛出异常时,情况很难调试。弹出窗口显示异常信息,而不是被调试器捕获。此外,the thread seems to be restarted,并且作为编码错误的结果的例外,它会一次又一次地显示。

当我很幸运地切换到调试器时(这很困难,因为越来越多的弹出窗口随着应用程序获取绘制请求而不断出现),调试控制台向我显示了一个异常信息,如:

  

严重:线程中抛出未捕获的异常[AWT-EventQueue-0,6,main]

     

.... stack跟随

我的应用程序是用Scala编写的,我使用的是IntelliJ IDEA 14.我的未被捕获的主线程异常由调试器处理得很好(我Uncaught exception启用了Any exceptionJava Exception Breakpoints中启用了断点但是,AWT线程中的异常不是。

我已尝试安装this How can I detect when an Exception's been thrown globally in Java? answer中描述的处理程序,但我的处理程序似乎没有被触发。

我想实现以下(按重要性顺序):

  1. 避免AWT线程在异常时重新启动,或者至少阻止弹出窗口显示
  2. 在调试器中处理未捕获的异常,而不是在控制台中打印
  3. (注意:虽然这是Scala应用程序,但我认为Java的行为是相同的,因此是Java标记)。

3 个答案:

答案 0 :(得分:9)

根据此link,您必须同时处理常规ExceptionEDT Exception而不使用旧的sun.awt.exception.handler黑客(自Java 7以来不再有效)< / p>

这是您的ExceptionHandler

public static class ExceptionHandler implements Thread.UncaughtExceptionHandler
{
    public void uncaughtException(Thread thread, Throwable thrown)
    {
        // TODO handle your Exception here
    }
}

用法:

// Regular Exception
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());

// EDT Exception
SwingUtilities.invokeAndWait(new Runnable()
{
    public void run()
    {
        // We are in the event dispatching thread
        Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());
    }
});

答案 1 :(得分:0)

  

在Java中

你的问题是异常被抛出在另一个线程中,即事件调度线程。几个解决方案:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    public void uncaughtException(Thread t, Throwable e) {
        logger.error("Uncaught exception in thread: " + t.getName, e);
    }
});

在任何情况下,您原则上都应该使用

中的UI启动代码
EventQueue.invokeLater();
直接调用它的

SwingUtilities.invokeLater()

  

在Scala中

你的问题是异常被抛出在另一个线程中,即事件调度线程。几个解决方案:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
  def uncaughtException(t: Thread, e: Throwable) {
    logger.error("Uncaught exception in thread: " + t.getName, e)
  }
})

在任何情况下,您原则上都应该使用

中的UI启动代码
EventQueue.invokeLater()

答案 2 :(得分:0)

看起来您唯一的解决方案可能是切换到Eclipse。 :-)其他解决方案需要编码工作,并且在异常处理程序中停止与在抛出异常的确切位置停止不同。

使用以下程序,我在Eclipse中监听被捕获/未被捕获的RuntimeException实例时没有任何问题。

package lambda;

import java.awt.Dimension;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class AWTExceptionTest {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Test");
        button.addActionListener(e -> { throw new RuntimeException(); });
        frame.add(button);
        frame.setSize(new Dimension(50, 50));
        SwingUtilities.invokeLater(() -> frame.setVisible(true));
    }
}

以下是Eclipse中调试模式的外观。

Eclipse in Debug mode