如何捕获事件调度线程(EDT)异常? [英] How can i catch Event Dispatch Thread (EDT) exceptions?
问题描述
我正在使用一个名为 MyExceptionHandler
的类实现 Thread.UncaughtExceptionHandler
来处理我的项目中的正常异常。 / p>
据了解,这个类不能捕获EDT异常,所以我试图在 main()
方法来处理EDT异常:
public static void main(final String [] args){
Thread.setDefaultUncaughtExceptionHandler (new MyExceptionHandler()); //处理正常的异常
System.setProperty(sun.awt.exception.handler,MyExceptionHandler.class.getName()); //处理EDT异常
SwingUtilities.invokeLater(new Runnable(){//在EDT中执行一些代码
public void run(){
JFrame myFrame = new JFrame();
myFrame.setVisible(true);
}
});
}
但直到现在它不工作。例如,在初始化JFrame时,我从构造函数中的bundle文件中加载它的标签,如下所示:
setTitle(bundle.getString( MyJFrame.title));
我删除了密钥 MyJFrame.title
该bundle文件来测试异常处理程序,但它没有工作!
我在这里做错了吗?
EDT异常处理程序不使用 Thread.UncaughtExceptionHandler
。相反,它调用一个具有以下签名的方法:
public void handle(Throwable throwwn);
将其添加到 MyExceptionHandler
,它应该
文档在 EventDispatchThread
中找到,这是一个包私有类, code> java.awt中。引用来自 handleException()
的javadoc:
/ **
*处理事件发送线程中抛出的异常。
*
*< p>如果系统属性sun.awt.exception.handler被定义,那么当调用此方法时,
*将尝试执行以下操作:
*
*< ol>
*< li>使用
*当前线程的上下文类加载器
*< li>加载由该属性的值命名的类使用其零参数构造函数
*< li>实例化该类找到结果处理程序对象的< tt> public void handle< / tt>
*方法,它应该采用
*< tt> Throwable< / tt>和
*< li>的单个参数。调用处理程序的< tt>句柄< / tt>方法,传递
*< tt>抛出< / tt>传递给这个方法的参数。
*< / ol>
*
*如果前三个步骤中的任何一个失败,则此方法将返回
*< tt> false< / tt>并且此方法的所有以下调用将返回
*< tt> false< / tt>立即。处理程序对象的
*< tt> handle< / tt>抛出的异常将被捕获,并将导致此方法返回
*< tt> false< / tt> ;.如果处理程序的< tt>句柄< / tt>方法成功调用
*,那么这个方法将返回< tt> true< / tt> ;.这个方法将
*不会抛出任何异常。
*
*< p> < I>注意:< I> /;这种方法是一个临时的黑客,可以解决
*缺少真正的API,提供替换
*事件调度线程的能力。魔术sun.awt.exception.handler属性
*< i>将被删除< / i>在将来的版本中。
* /
Sun希望如何找到这个,我不知道。 p>
这是一个完整的例子,它捕获了EDT和EDT之间的异常:
import javax.swing.SwingUtilities;
public class Test {
public static class ExceptionHandler
implements Thread.UncaughtExceptionHandler {
public void handle(Throwable throwwn){
/ / for EDT exception
handleException(Thread.currentThread()。getName(),throwwn);
}
public void uncaughtException(Thread thread,Throwable throwwn){
// for other uncaught exceptions
handleException(thread.getName(),throwwn);
}
protected void handleException(String tname,Throwable throwwn){
System.err.println(Exception on+ tname);
thrown.printStackTrace();
}
}
public static void main(String [] args){
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
System.setProperty(sun.awt.exception.handler,
ExceptionHandler.class.getName());
//在EDT上引发异常
SwingUtilities.invokeLater(new Runnable(){
public void run(){
((Object)null)。 toString();
}
});
//导致EDT
((Object)null)的异常.toString();
}
}
应该这样做。
I am using a class called MyExceptionHandler
that implements Thread.UncaughtExceptionHandler
to handle normal exceptions in my project.
As I understand this class can't catch the EDT exceptions, so I tried to use this in the main()
method to handle EDT exceptions:
public static void main( final String[] args ) {
Thread.setDefaultUncaughtExceptionHandler( new MyExceptionHandler() ); // Handle normal exceptions
System.setProperty( "sun.awt.exception.handler",MyExceptionHandler.class.getName()); // Handle EDT exceptions
SwingUtilities.invokeLater(new Runnable() { // Execute some code in the EDT.
public void run() {
JFrame myFrame = new JFrame();
myFrame.setVisible( true );
}
});
}
But untill now it's not working. For example while initializing a JFrame I load its labels from a bundle file in the constructor like this:
setTitle( bundle.getString( "MyJFrame.title" ) );
I deleted the key MyJFrame.title
from the bundle file to test the exception handler, but it didn't work! The exception was normally printed in the log.
Am I doing something wrong here?
The EDT exception handler doesn't use Thread.UncaughtExceptionHandler
. Instead, it calls a method with the following signature:
public void handle(Throwable thrown);
Add that to MyExceptionHandler
, and it should work.
The "documentation" for this is found in EventDispatchThread
, which is a package-private class in java.awt
. Quoting from the javadoc for handleException()
there:
/**
* Handles an exception thrown in the event-dispatch thread.
*
* <p> If the system property "sun.awt.exception.handler" is defined, then
* when this method is invoked it will attempt to do the following:
*
* <ol>
* <li> Load the class named by the value of that property, using the
* current thread's context class loader,
* <li> Instantiate that class using its zero-argument constructor,
* <li> Find the resulting handler object's <tt>public void handle</tt>
* method, which should take a single argument of type
* <tt>Throwable</tt>, and
* <li> Invoke the handler's <tt>handle</tt> method, passing it the
* <tt>thrown</tt> argument that was passed to this method.
* </ol>
*
* If any of the first three steps fail then this method will return
* <tt>false</tt> and all following invocations of this method will return
* <tt>false</tt> immediately. An exception thrown by the handler object's
* <tt>handle</tt> will be caught, and will cause this method to return
* <tt>false</tt>. If the handler's <tt>handle</tt> method is successfully
* invoked, then this method will return <tt>true</tt>. This method will
* never throw any sort of exception.
*
* <p> <i>Note:</i> This method is a temporary hack to work around the
* absence of a real API that provides the ability to replace the
* event-dispatch thread. The magic "sun.awt.exception.handler" property
* <i>will be removed</i> in a future release.
*/
How exactly Sun expected you find this, I have no idea.
Here's a complete example which catches exceptions both on and off the EDT:
import javax.swing.SwingUtilities;
public class Test {
public static class ExceptionHandler
implements Thread.UncaughtExceptionHandler {
public void handle(Throwable thrown) {
// for EDT exceptions
handleException(Thread.currentThread().getName(), thrown);
}
public void uncaughtException(Thread thread, Throwable thrown) {
// for other uncaught exceptions
handleException(thread.getName(), thrown);
}
protected void handleException(String tname, Throwable thrown) {
System.err.println("Exception on " + tname);
thrown.printStackTrace();
}
}
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
System.setProperty("sun.awt.exception.handler",
ExceptionHandler.class.getName());
// cause an exception on the EDT
SwingUtilities.invokeLater(new Runnable() {
public void run() {
((Object) null).toString();
}
});
// cause an exception off the EDT
((Object) null).toString();
}
}
That should do it.
这篇关于如何捕获事件调度线程(EDT)异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!