2010-12-15 4 views
18

MyExceptionHandlerというクラスを使用しています。これはThread.UncaughtExceptionHandlerを実装しており、私のプロジェクトで通常の例外を処理しています。Event Dispatch Thread(EDT)の例外をどのように捕まえることができますか?

私は、このクラスは、EDTの例外をキャッチすることはできませんので、私はEDTの例外を処理するためにmain()方法でこれを使用しようとした理解したよう:

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); 
     } 
    }); 
} 

しかし、それまでは、今、それは働いていません。私はこのようなコンストラクタでバンドル・ファイルからラベルをロードしたJFrameの初期化中にたとえば:

setTitle(bundle.getString("MyJFrame.title")); 

私は、例外ハンドラをテストするために、バンドルファイルからキーMyJFrame.titleを削除したが、それはうまくいきませんでした!例外は通常、ログに出力されました。

ここで何か問題がありますか?

+0

可能な複製[JavaでAWTスレッドの例外を捕捉する方法はありますか?](http://stackoverflow.com/questions/95767/how-can-i-catch-awt-thread-exceptions- in-java) – Suma

答えて

29

EDT例外ハンドラはThread.UncaughtExceptionHandlerを使用しません。代わりに、それは次のシグネチャを持つメソッドを呼び出します。

public void handle(Throwable thrown); 

MyExceptionHandlerにそれを追加し、それが動作するはずです。

java.awtのパッケージプライベートクラスであるEventDispatchThreadに「ドキュメント」があります。そこhandleException()のJavadocから引用:

/** 
* 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. 
*/ 

日は、あなたがこれを見つけると予想方法を正確に、私は考えています。

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(); 
    } 
} 

それを行う必要があります。

はここで両方のオンとオフEDT例外をキャッチし、完全な例です。

+0

@uckelman ...あなたが言いましたが、例外は捕まえられていませんでした! ... public void handle(Throwable throw){ \t \t System.out.println( "例外がキャッチされました"); //ボットを印刷しました! \t} – Brad

+0

@Brad:EDTで例外が発生しないため、上記の例では 'Brad:' handle() 'は実行されません。例外を強制するには 'JFrame frame = null;'を試してください。 – uckelman

+0

@uckelman ...あなたが言及した例に従えば、例外はhandle(...)によって処理されます。そしてhandle(...)が存在しない場合でも、例外は実装されたメソッドuncaughtException(...)によって処理され、handle(...)の必要はありません!しかし、完全に失敗するケースは、私がJFrameを初期化してから別のJFrameを開いて、私の質問で述べたようにそのバンドルファイルのタイトルが見付からない場合です。この例外はhandle(...)やncaughtException(...)では処理されませんが、ログにのみ出力されます。 – Brad

0

多くの場合、いくつかの追加情報のために、Throwableは1.5と1.6であってもEDTのUncaughtExceptionHandlerによってキャッチされることがあります。

    1. のThrowableは次のとおりです。このコードによると、Throwableのは、EDTスレッドのたuncaughtExceptionHandlerによってキャッチされることはありませんだけで3つの方法があります

      private void processException(Throwable e, boolean isModal) { 
          if (!handleException(e)) { 
           // See bug ID 4499199. 
           // If we are in a modal dialog, we cannot throw 
           // an exception for the ThreadGroup to handle (as added 
           // in RFE 4063022). If we did, the message pump of 
           // the modal dialog would be interrupted. 
           // We instead choose to handle the exception ourselves. 
           // It may be useful to add either a runtime flag or API 
           // later if someone would like to instead dispose the 
           // dialog and allow the thread group to handle it. 
           if (isModal) { 
            System.err.println(
             "Exception occurred during event dispatching:"); 
            e.printStackTrace(); 
           } else if (e instanceof RuntimeException) { 
            throw (RuntimeException)e; 
           } else if (e instanceof Error) { 
            throw (Error)e; 
           } 
          } 
      } 
      
      private boolean handleException(Throwable thrown) { 
      
          try { 
      
           if (handlerClassName == NO_HANDLER) { 
            return false; /* Already tried, and failed */ 
           } 
      
           /* Look up the class name */ 
           if (handlerClassName == null) { 
            handlerClassName = ((String) AccessController.doPrivileged(
             new GetPropertyAction(handlerPropName))); 
            if (handlerClassName == null) { 
             handlerClassName = NO_HANDLER; /* Do not try this again */ 
             return false; 
            } 
           } 
      
           /* Load the class, instantiate it, and find its handle method */ 
           Method m; 
           Object h; 
           try { 
            ClassLoader cl = Thread.currentThread().getContextClassLoader(); 
            Class c = Class.forName(handlerClassName, true, cl); 
            m = c.getMethod("handle", new Class[] { Throwable.class }); 
            h = c.newInstance(); 
           } catch (Throwable x) { 
            handlerClassName = NO_HANDLER; /* Do not try this again */ 
            return false; 
           } 
      
           /* Finally, invoke the handler */ 
           m.invoke(h, new Object[] { thrown }); 
      
          } catch (Throwable x) { 
           return false; 
          } 
      
          return true; 
      } 
      

      :1.5.0_22にEventDispatchThreadのソースコードを見てみます成功しsun.awt.exception.handlerで扱う(クラスをインスタンス化、発見され、そのハンドル(Throwableを)メソッドは、何も投げずに呼ばれた)のThrowableがどちらのRuntimeException nはモーダルダイアログ

    2. EDTですがまたはエラー