2010-12-15 2 views
18

MyExceptionHandler이라는 클래스를 사용하고 있는데, 이는 내 프로젝트에서 일반적인 예외를 처리하기 위해 Thread.UncaughtExceptionHandler을 구현합니다. 나는이 클래스는 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); 
     } 
    }); 
} 

을하지만 지금은 작동하지 않습니다 전까지.

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

내가 예외 핸들러를 테스트하기 위해 번들 파일에서 키 MyJFrame.title을 삭제했지만 작동하지 않았다 : JFrame의 초기화 예를 들어이 같은 생성자에서 번들 파일에서의 라벨을로드! 예외는 일반적으로 로그에 인쇄되었습니다.

여기 뭔가 잘못 되었나요?

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

을 수행해야합니다

여기에서 모두와 동부 서머 타임 오프 예외를 잡는다 완벽한 예입니다.

+0

@uckelman ... 나는 당신이 언급 한 것을했지만, 예외는 잡히지 않았다! ... public void handle (Throwable Throw) { \t \t System.out.println ("Exception is Catched"); // 봇 프린트를 했습니까! \t} – Brad

+0

@Brad : 거기에서 EDT에 예외가 일어나지 않기 때문에 위의 예제에서'Brad :'handle()'이 실행되지 않습니다. 예외를 강제하려면'JFrame frame = null; '을 시도하십시오. – uckelman

+0

@uckelman ... 언급 한 예제를 따르는 경우 언급 한대로 예외 (...)가 처리됩니다. 그리고 handle (...)이 존재하지 않는 경우에도 예외는 구현 된 메소드 uncaughtException (...)에 의해 처리되며 handle (...)이 필요 없습니다! 하지만 완전히 실패한 경우는 JFrame을 초기화 한 다음 내 질문에서 언급 한 것처럼 번들 파일에서 제목이 누락 된 다른 JFrame을 열면됩니다. 이 예외는 handle (...)이나 ncaughtException (...)에 의해 처리되지 않고 로그에만 인쇄됩니다. – Brad

0

단지 몇 가지 추가 정보로, 많은 경우 Throwables가 1.5와 1.6에서도 EDT의 UncaughtExceptionHandler에 의해 잡힐 수 있습니다. 1.5.0_22에서 EventDispatchThread로의 소스 코드를 보면 :

  1. throw 가능 객체가된다

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

    를이 코드에 따르면,의 Throwable은 EDT 스레드의 있던 uncaughtExceptionHandler에 의해 체포되지 않습니다 단지 3 가지 방법이 있습니다 sun.awt.exception.handler가 성공적으로 처리 함 (클래스가 발견되고 인스턴스화되었으며 아무 것도 던지지 않고 호출 된 처리 (Throwable) 메서드)

  2. EDT가 모달 대화 상자에 있음
  3. Throwable은 RuntimeException이 아니며 n 또는 오류