8

Thread.UncaughtExceptionHandler besagt, dass, wenn die Methode, die nicht abgefangene Ausnahmen behandelt selbst eine Ausnahme auslöst, wird diese Ausnahme ignoriert:Werden Fehler, die in UncaughtExceptionHandler geworfen werden, verschluckt?

void uncaughtException(Thread t, Throwable e):

Method invoked when the given thread terminates due to the given uncaught exception.

Any exception thrown by this method will be ignored by the Java Virtual Machine.

Jedoch, wenn ich es getestet habe die JVM die Ausnahmen nicht ignorieren die abgefangene Ausnahme handler` behandelt

public static void main(final String args[]) { 
    Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
     @Override 
     public void uncaughtException(Thread arg0, Throwable arg1) { 
      throw new java.lang.RuntimeException("e2"); 
     } 
    }); 
    throw new RuntimeException("e1"); 
} 

Eclipse-Console-Ausgang (JRE 1.7):

Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "main"

Ein weiterer o ddity Ich fand heraus, dass die Ausgabe, die ich bekomme, nicht von System.err kommt. Es scheint von einem anderen Strom zusammen zu sein. Ich überprüfte dies durch System.err zu System.out Umleitung, aber ich bin immer noch „rot“ Ausgabe bekommen:

public static void main(final String[] args) { 
    System.setErr(System.out); 
    System.out.println(System.err == System.out); 
    System.err.println("this is black color"); 
    try { 
     throw new Error("test stacktrace color"); 
    } catch (Throwable e) { 
     e.printStackTrace(); 
    } 
    try { 
     Thread.sleep(2500); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
     @Override 
     public void uncaughtException(Thread t, Throwable e) { 
      throw new RuntimeException("from handler"); 
     } 
    }); 
    throw new RuntimeException("from main"); 
} 

Der Ausgang (bolded rot bedeutet Farbe):

true

this is black color

java.lang.Error: test stacktrace color at asf.df.main(df.java:13)

Exception: java.lang.RuntimeException thrown from the UncaughtExceptionHandler in thread "main"

Was ist die Erklärung für diese Phänomene?

Was passiert mit Fehlern, die in UncaughtExceptionHandler geworfen werden? Was ist das erwartete (dokumentierte oder garantierte) Verhalten?

+0

Möglicherweise versionsspezifisch? –

+0

Bereits in früheren Java-Versionen wurde von den Dokumenten angegeben, dass sie von der JVM ignoriert werden sollten. – Pacerier

+0

In Oracle "1.6.0_39"/Ubuntu 12.04 wird die Ausnahme, die innerhalb des nicht abgefangenen Ausnahmebehandlers ausgelöst wird, von der JVM geschluckt. Wie @Andrew_CS sagte, könnte es versions-/herstellerspezifisch sein. – srkavin

Antwort

5

HotSpot JVM gibt die Ausnahmen aus, die vom UncaughtExceptionHandler ausgelöst wurden. Siehe JavaThread::exit

if (HAS_PENDING_EXCEPTION) { 
     ResourceMark rm(this); 
     jio_fprintf(defaultStream::error_stream(), 
      "\nException: %s thrown from the UncaughtExceptionHandler" 
      " in thread \"%s\"\n", 
      pending_exception()->klass()->external_name(), 
      get_thread_name()); 
     CLEAR_PENDING_EXCEPTION; 
    } 

JVM druckt diese Ausnahme selbst direkt auf stderr unabhängig von dem System.err Zustand - ob umgeleitet wurde oder nicht.

Nun, diese Art der Warnung hat keinen Einfluss auf die Anwendung - in diesem Sinne wird die Ausnahme "ignoriert". Aber du hast Recht, dieses Verhalten ist nicht offensichtlich. Javadoc ist irreführend und sollte besser repariert werden.

+0

+1, aber ist es nicht anders herum, dass HotSpot repariert werden sollte, um die JLS zu halten? – Pacerier

+1

Ich denke nicht, dass es eine gute Idee ist, Ausnahmen stillschweigend zu ignorieren. Solche Fälle wären schwer zu debuggen. Übrigens ist dies nur eine API-Dokumentation, die nicht Teil von JLS oder JVMS ist. Javadoc neigt dazu, veraltet zu werden, wenn sich die Implementierung ändert - dies geschieht ziemlich oft aufgrund von Leistungsoptimierungen, neuen Funktionen usw. Beispielsweise wird der Standard-'hashCode' üblicherweise durch Konvertieren einer internen Objektadresse implementiert, aber dies gilt nicht für HotSpot JVM. – apangin

2

Die Ausnahmen werden ignoriert und die Verarbeitung wird fortgesetzt, wenn sie von einem Nicht-Hauptthread ausgelöst wird.

Wenn es in main geworfen wird, ist der zurückgegebene Fehlercode ungleich Null.

Die nicht behandelten Ausnahmen werden über syserr protokolliert.

public static void main(final String[] args) { 

    final Thread myThread = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      Thread.currentThread() 
       .setUncaughtExceptionHandler(new UncaughtExceptionHandler() { 

        @Override 
        public void uncaughtException(final Thread t, final Throwable e) { 

         System.out.println("In child UncaughtExceptionHandler at " + java.time.Instant.now()); 

         throw new RuntimeException("From child thread UncaughtExceptionHandler" 
           + java.time.Instant.now()); 

        } 
       }); 
      throw new RuntimeException("from runnable"); 
     } 
    }); 

    Thread.currentThread() 
    .setUncaughtExceptionHandler(new UncaughtExceptionHandler() { 

     @Override 
     public void uncaughtException(final Thread t, final Throwable e) { 

       System.out.println("In main UncaughtExceptionHandler " + java.time.Instant.now()); 

       throw new RuntimeException("From main thread UncaughtExceptionHandler" + java.time.Instant.now()); 

     } 
    }); 

    myThread.start(); 

    LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2)); 

    System.out.println("After child thread: " + java.time.Instant.now()); 

    //Will result in a non-zero return code 
    throw new RuntimeException("from main"); 
} 

Ausgang:

In Kind UncaughtExceptionHandler bei 2014-07-19T04: 10: 46.184Z

Ausnahme: java.lang.RuntimeException vom UncaughtExceptionHandler in thread „geworfen Faden 0 " Nach Kind thread: 2014-07-19T04: 10: 48.197Z Im Haupt UncaughtExceptionHandler 2014-07-19T04: 10: 48.197Z

Ausnahme: java.l ang.RuntimeException wird vom UncaughtExceptionHandler im Thread "main" ausgelöst

+0

Aus Ihrer Ausgabe sehen wir "Ausnahme: java.lang.RuntimeException ausgelöst von der UncaughtExceptionHandler in Thread Thread-0". Wenn ja, warum sagst du, dass die Ausnahme ignoriert wird, wenn sie aus einem Nicht-Haupt-Thread geworfen wird? – Pacerier

+0

Es schreibt nach syserr, aber Ausnahmen, die in Nicht-Haupt-Thread-Handlern ausgelöst werden, werden nicht propagiert und ändern den Rückkehrcode beim Beenden nicht. Von einem Ausführungsstandpunkt aus werden sie ignoriert. – Jeff

+0

** 1) ** Es wird nicht in system.error geschrieben. Ich habe das versucht, indem ich System.err auf System.out umgeleitet habe (siehe das zweite Code-Snippet in der Frage), aber die Ausgabe ist immer noch rot. ** 2) ** Und natürlich propagieren Ausnahmen in verschiedenen Threads nicht miteinander, unabhängig davon, ob wir UncaughtExceptionHandler verwendet haben oder nicht .... – Pacerier

Verwandte Themen