In einem Kommentar (von user soc ) zu einer Antwort auf eine Frage zur Tail-Call-Optimierung wurde erwähnt, dass Java 7 aufgrund der "Hinzufügung von ARM" (Unterstützung für ARM-CPUs?) Eine neue Funktion namens "Unterdrückte Ausnahmen" hat.
Was ist in diesem Zusammenhang eine "unterdrückte Ausnahme"? In anderen Kontexten wäre eine "unterdrückte Ausnahme" eine Ausnahme, die abgefangen und dann ignoriert wurde (selten eine gute Idee). das ist eindeutig etwas anderes.
Antworten:
Ich glaube, der Kommentator bezieht sich auf eine Ausnahme, die teilweise ignoriert wird, wenn sie im impliziten
finally
Block eines Try-with-Resources- Blocks im Kontext einer vorhandenen Ausnahme ausgelöst wird, die aus demtry
Block ausgelöst wird :(Das zitiert einen Abschnitt namens "Unterdrückte Ausnahmen" von der verlinkten Seite.)
quelle
finally
Block eine Ausnahme auslöst, wenn dertry
Block auch eine Ausnahme auslöst, die ursprüngliche Ausnahme von dertry
Block ist verloren oder "unterdrückt" ( weitere Informationen finden Sie unter http://accu.org/index.php/journals/236 ). Java 7 hat gerade eine bequeme Methode zum Speichern der Ausnahme aus demfinally
Block hinzugefügt , da diesefinally
implizit durch Try-with-Resources generiert wird.Um das Zitat in Jons Antwort zu verdeutlichen, kann nur eine Ausnahme von einer Methode (pro Ausführung)
try-with-resources
ausgelöst werden. Im Fall von a können jedoch mehrere Ausnahmen ausgelöst werden. Zum Beispiel könnte einer in den Block geworfen werden und ein anderer könnte aus dem impliziten geworfen werden, der von derfinally
bereitgestellt wirdtry-with-resources
.Der Compiler muss bestimmen, welche davon "wirklich" geworfen werden sollen. Es wird entschieden, die im expliziten Code (dem Code im
try
Block) ausgelöste Ausnahme anstelle der vom impliziten Code (demfinally
Block) ausgelösten Ausnahme auszulösen . Daher werden die im impliziten Block ausgelösten Ausnahmen unterdrückt (ignoriert). Dies tritt nur bei mehreren Ausnahmen auf.quelle
try
...finally
Klauseln mehr schreiben müssenclose()
: stackoverflow.com/questions/3305405/…Exception(Exception cause)
Konstruktor wird verwendet, um eine verursachende Ausnahme in eine andere zu verpacken, die möglicherweise aussagekräftiger ist. In diesem Fall handelt es sich jedoch um zwei unterschiedliche Ausnahmen, für die kein Kausalzusammenhang besteht. Ausnahme A hat keine Ausnahme B verursacht, daher wäre es nicht sinnvoll, eine in die andere zu wickeln. Außerdem nehmen Sie an, dass der Codierer die zweite Ausnahme explizit auslöst und Zugriff auf die erste hat. Dies wäre nicht der Fall, wenn beide durch Bibliotheksaufrufe ausgelöst würden.If an exception is thrown from the try block and one or more exceptions are thrown from the try-with-resources statement, then those exceptions thrown from the try-with-resources statement are suppressed
Vor Java7; Es gibt Ausnahmen im Code, die aber irgendwie ignoriert wurden.
z.B)
public class SuppressedExceptions { public static void main(String[] args) throws Exception { try { callTryFinallyBlock(); } catch (Exception e) { e.printStackTrace(); **//Only Finally Exception is Caught** } } private static void callTryFinallyBlock() throws Exception { try { throw new TryException(); **//This is lost** } finally { FinallyException fEx = new FinallyException(); throw fEx; } } } class TryException extends Exception { } class FinallyException extends Exception { }
Ein neuer Konstruktor und zwei neue Methoden wurden der Throwable-Klasse in JDK 7 hinzugefügt. Diese sind wie folgt:
Throwable.getSupressed(); // Returns Throwable[] Throwable.addSupressed(aThrowable);
Mit diesem neuen Ansatz können wir auch diese unterdrückten Ausnahmen behandeln.
public class SuppressedExceptions { public static void main(String[] args) throws Exception { try { callTryFinallyBlock(); } catch (Exception e) { e.printStackTrace(); for(Throwable t: e.getSuppressed()) { t.printStackTrace(); } } } private static void callTryFinallyBlock() throws Exception { Throwable t = null; try { throw new TryException(); } catch (Exception e) { t = e; } finally { FinallyException fEx = new FinallyException(); if(t != null)fEx.addSuppressed(t); throw fEx; } } } class TryException extends Exception { } class FinallyException extends Exception { }
Beachten Sie auch, dass sich dies von verketteten Ausnahmen unterscheidet (wurden mit JDK 1.4 eingeführt und sollten es ermöglichen, Kausalzusammenhänge zwischen Ausnahmen leicht zu verfolgen).
quelle
Den folgenden Code einräumen:
public class MultipleExceptionsExample { static class IOManip implements Closeable{ @Override public void close() { throw new RuntimeException("from IOManip.close"); } } public static void main(String[] args) { try(IOManip ioManip = new IOManip()){ throw new RuntimeException("from try!"); }catch(Exception e){ throw new RuntimeException("from catch!"); }finally{ throw new RuntimeException("from finally!"); } } }
Mit allen Zeilen erhalten Sie:
java.lang.RuntimeException: from finally!
Wenn
finally
Sie den Block entfernen , erhalten Sie:java.lang.RuntimeException: from catch!
Wenn
catch
Sie den Block entfernen , erhalten Sie:Exception in thread "main" java.lang.RuntimeException: from try! Suppressed: java.lang.RuntimeException: from IOManip.close
quelle
Unterdrückte Ausnahmen sind zusätzliche Ausnahmen, die in einer Try-with-Resources-Anweisung ( eingeführt in Java 7 ) auftreten, wenn
AutoCloseable
Ressourcen geschlossen werden. Da beim Schließen vonAutoCloseable
Ressourcen mehrere Ausnahmen auftreten können, werden zusätzliche Ausnahmen als unterdrückte Ausnahmen an eine primäre Ausnahme angehängt .Beim Betrachten des Bytecodes eines Beispielcodes für den Versuch mit Ressourcen werden Standard- JVM-Ausnahmebehandlungsroutinen verwendet, um die Semantik für den Versuch mit Ressourcen zu berücksichtigen.
quelle
Sie können Ausnahmen auch in Java 6 unterdrücken (ein kleiner Trick).
Ich habe ein Dienstprogramm erstellt, das das Unterdrücken von Ausnahmen in Java 1.6 und Java 1.7 transparent behandelt. Die Implementierung finden Sie hier
Sie müssen nur anrufen:
public static <T extends Throwable> T suppress(final T t, final Throwable suppressed)
eine Ausnahme unterdrücken, und
public static Throwable [] getSuppressed(final Throwable t) {
um die unterdrückten Ausnahmen einer Ausnahme zu erhalten, falls noch jemand Java 1.6 verwendet
quelle
ARM - Automatisches Ressourcenmanagement (eingeführt seit Java 7)
Nehmen Sie ein sehr einfaches Beispiel
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { if (br != null) br.close(); } }
Wenn nun die
readLine()
Funktion eine Ausnahme auslöst und dann sogar dieclose()
Funktion [im Endblock] eine Ausnahme auslöst, erhält die letztere eine höhere Priorität und wird zurück zur aufrufenden Funktion geworfen. In diesem Fall ist dieException thrown by the readLine() method is ignored/suppressed
. Sie können die verursachende Ausnahme in Ihrer Ausnahme verketten und Ihre Ausnahme aus dem endgültigen Blockieren erneut werfen.Da
java 7
Funktionen zum Abrufen unterdrückter Ausnahmen bereitgestellt wurden. Sie können diepublic final java.lang.Throwable[] getSuppressed()
Funktion für das abgefangene Wurfobjekt aufrufen, um die unterdrückten Ausnahmen anzuzeigen.Zum Beispiel.
static String readFirstLineFromFileWithFinallyBlock(String path) throws Exception { try (BufferedReader br = new BufferedReader(new FileReader(path));) { return br.readLine(); } }
Wenn nun beim Schließen der Ressource eine
br.readLine();
Zeile ausgelöstException1
und dannException2
beispielsweise ausgelöst wird [Stellen Sie sich vor, dies geschieht in einem impliziten Endblock, den die Anweisung "try-with-resource" erstellt], unterdrückt Exception1 Exception2.Einige Punkte, die hier zu beachten sind -
Ich habe die meisten möglichen Szenarien mit Codefragmenten kompiliert und im folgenden Beitrag ausgegeben.
Unterdrückte Ausnahmen in Java 7
Hoffentlich hilft das.
quelle
Exception
aus dem try {} -Block stammende Block jedoch nicht automatisch unterdrückt. Der Programmierer kann sich dafür entscheiden, was Sie nicht getan haben. Nur Versuche mit Ressourcen werden Ausnahmen bei Bedarf automatisch unterdrücken. Und wenn er es tut, wird die Ausnahme von Ihrem äquivalenten Endblock unterdrückt.Ich denke, das hat mit der "verketteten Ausnahmefunktion" zu tun. Dies wirkt sich darauf aus, wie eine Ausnahme von dieser Funktion behandelt wird, wenn sich die Stapelverfolgung weiterentwickelt. Im Laufe der Zeit können Ausnahmen, die Teil einer Gruppe verketteter Ausnahmen sind, unterdrückt werden. Weitere Informationen finden Sie in der Throwable-Dokumentation .
quelle