Wann java.lang.Error zu fangen?

In welchen Situationen sollte man java.lang.Error in einer Anwendung abfangen?

Generell nie. Manchmal müssen Sie jedoch bestimmte Fehler abfangen.

Wenn Sie Framework-ish-Code schreiben (dh classn von Drittanbietern laden), ist es ratsam, LinkageErrors zu erfassen (keine gefundene class def, nicht erfüllter Link, nicht kompatible classnänderung). Ich habe auch einen dummen Code von Drittanbietern gesehen, der Subklischees von Fehlern geworfen hat, also musst du auch mit diesen umgehen.

Ich bin mir übrigens nicht sicher, dass es nicht möglich ist, sich von OutOfMemory zu erholen.

Noch nie. Sie können nie sicher sein, dass die Anwendung die nächste Codezeile ausführen kann. Wenn Sie einen OutOfMemoryError , haben Sie keine Garantie, dass Sie etwas Verlässliches tun können . Catch RuntimeException und überprüfte Ausnahmen, aber nie Fehler.

http://pmd.sourceforge.net/rules/strictexception.html

Generell sollten Sie java.lang.Error immer abfangen und in ein Protokoll schreiben oder dem Benutzer anzeigen. Ich arbeite im Support und sehe täglich, dass Programmierer nicht wissen können, was in einem Programm passiert ist.

Wenn Sie einen Daemon-Thread haben, müssen Sie verhindern, dass er beendet wird. In anderen Fällen wird Ihre Anwendung ordnungsgemäß funktionieren.

Sie sollten java.lang.Error auf höchster Ebene abfangen.

Wenn Sie sich die Liste der Fehler ansehen, werden Sie sehen, dass die meisten behandelt werden können. Zum Beispiel tritt ein ZipError beim Lesen von ZipError Zip-Dateien auf.

Die häufigsten Fehler sind OutOfMemoryError und NoClassDefFoundError , die beide in den meisten Fällen Laufzeitprobleme sind.

Beispielsweise:

 int length = Integer.parseInt(xyz); byte[] buffer = new byte[length]; 

kann einen OutOfMemoryError erzeugen, aber es ist ein Laufzeitproblem und kein Grund, das Programm zu beenden.

NoClassDefFoundError tritt meistens auf, wenn eine Bibliothek nicht vorhanden ist oder wenn Sie mit einer anderen Java-Version arbeiten. Wenn es sich um einen optionalen Teil Ihres Programms handelt, sollten Sie Ihr Programm nicht beenden.

Ich kann viele weitere Beispiele geben, warum es Throwable ist, Throwable auf oberster Ebene zu Throwable und eine hilfreiche Fehlermeldung zu erzeugen.

In einer Multithread-Umgebung möchten Sie es am häufigsten erfassen! Wenn Sie es fangen, melden Sie es an und beenden Sie die gesamte Anwendung! Wenn Sie das nicht tun, wäre ein Thread, der einen entscheidenden Teil erledigen könnte, tot, und der Rest der Anwendung wird denken, dass alles normal ist. Daraus können viele unerwünschte Situationen entstehen. Ein kleines Problem ist, dass Sie das Problem nicht einfach finden können, wenn andere Threads einige Ausnahmen auslösen, weil ein Thread nicht funktioniert.

Zum Beispiel sollte Schleife normalerweise sein:

 try { while (shouldRun()) { doSomething(); } } catch (Throwable t) { log(t); stop(); System.exit(1); } 

Selbst in einigen Fällen würden Sie verschiedene Fehler anders behandeln wollen, zum Beispiel könnten Sie bei OutOfMemoryError die Anwendung regelmäßig schließen (vielleicht sogar Speicher freigeben und fortfahren), bei einigen anderen können Sie nicht viel tun.

Sehr selten.

Ich würde sagen nur auf der obersten Ebene eines Threads, um zu versuchen, eine Nachricht mit dem Grund für einen Thread zu sterben ausstellen.

Wenn Sie in einem Framework sind, das diese Art von Dingen für Sie erledigt, überlassen Sie es dem Framework.

Fast nie. Bei Fehlern handelt es sich um Probleme, mit denen Anwendungen im Allgemeinen nichts anfangen können. Die einzige Ausnahme könnte darin bestehen, die Darstellung des Fehlers zu behandeln, aber auch das läuft je nach Fehler möglicherweise nicht wie geplant ab.

Ein Error sollte normalerweise nicht erkannt werden , da dies auf einen anormalen Zustand hinweist, der niemals auftreten sollte .

Aus der Java-API-Spezifikation für die Error :

Ein Error ist eine Unterklasse von Throwable , die auf schwerwiegende Probleme hinweist, die eine sinnvolle Anwendung nicht zu Throwable versuchen sollte. Die meisten dieser Fehler sind abnormale Bedingungen. […]

Eine Methode muss in ihrer throws-Klausel keine Unterklassen von Error deklarieren, die während der Ausführung der Methode ausgetriggers, aber nicht abgefangen werden, da diese Fehler abnormale Bedingungen sind, die niemals auftreten sollten.

Wie die Spezifikation erwähnt, wird ein Error nur in Situationen ausgetriggers, in denen die Wahrscheinlichkeit hoch ist. Wenn ein Error auftritt, kann die Anwendung nur sehr wenig tun, und unter bestimmten Umständen befindet sich die Java Virtual Machine selbst möglicherweise in einem instabilen Zustand (wie z VirtualMachineError )

Obwohl ein Error eine Unterklasse von Throwable was bedeutet, dass er von einer try-catch Klausel abgefangen werden kann, wird er wahrscheinlich nicht wirklich benötigt, da die Anwendung in einem abnormalen Zustand ist, wenn ein Error von der JVM ausgetriggers wird.

Es gibt auch einen kurzen Abschnitt zu diesem Thema in Abschnitt 11.5 Die Ausnahmehierarchie der Java-Sprachspezifikation, 2. Ausgabe .

Wenn Sie verrückt genug sind, um ein neues Unit-Test-Framework zu erstellen, wird Ihr Test-Runner wahrscheinlich java.lang.AssertionError abfangen müssen, das von Testfällen ausgetriggers wird.

Ansonsten sehen Sie andere Antworten.

Und es gibt ein paar andere Fälle, in denen, wenn Sie einen Fehler bemerken , Sie ihn erneut versuchen müssen . Zum Beispiel sollte ThreadDeath niemals abgefangen werden, es kann ein großes Problem verursachen, wenn Sie es in einer geschlossenen Umgebung (zB einem Anwendungsserver) abfangen:

Eine Anwendung sollte Instanzen dieser class nur abfangen, wenn sie nach asynchroner Beendigung bereinigt werden muss. Wenn ThreadDeath von einer Methode abgefangen wird, ist es wichtig, dass sie erneut ausgetriggers wird, sodass der Thread tatsächlich abstirbt.

Sehr, sehr selten.

Ich habe es nur für einen sehr sehr spezifischen bekannten Fall gemacht. Zum Beispiel könnte java.lang.UnsatisfiedLinkError ausgetriggers werden, wenn zwei unabhängige ClassLoader dieselbe DLL laden. (Ich stimme zu, dass ich die JAR in einen gemeinsamen classnlader verschieben soll)

Am häufigsten ist jedoch, dass Sie Logging benötigen, um zu wissen, was passiert ist, wenn Nutzer sich beschweren. Sie möchten eine Nachricht oder ein Popup für den Benutzer, und dann still im Hintergrund.

Sogar Programmierer in C / C ++, sie poppen einen Fehler und erzählen etwas, was die Leute nicht verstehen, bevor es beendet wird (zB Speichererrors).

In einer Android-Anwendung erhalte ich einen java.lang.VerifyError . Eine Bibliothek, die ich verwende, wird auf Geräten mit einer alten Version des Betriebssystems nicht funktionieren und der Bibliothekscode wird einen solchen Fehler auslösen. Ich könnte natürlich den Fehler vermeiden, indem ich die Version von OS zur Laufzeit überprüfe, aber:

  • Das älteste unterstützte SDK kann sich in Zukunft für die spezifische Bibliothek ändern
  • Der Try-Catch-Fehlerblock ist Teil eines größeren Rückfallmechanismus. Einige spezielle Geräte, obwohl sie die Bibliothek unterstützen sollen, casting Ausnahmen. Ich fange VerifyError und alle Ausnahmen, um eine Rückfalllösung zu verwenden.

es ist ziemlich praktisch java.lang.AssertionError in einer Testumgebung zu finden …

Im Idealfall sollten wir keine Fehler behandeln. Es kann jedoch Fälle geben, in denen wir aufgrund von Rahmenbedingungen oder Anwendungen vorgehen müssen. Angenommen, ich habe einen XML-Parser-Daemon, der den DOM-Parser implementiert, der mehr Speicher verbraucht. Wenn eine Anforderung wie der Parser-Thread bei OutOfMemoryError nicht gelöscht werden sollte , sollte sie stattdessen behandelt werden und eine Nachricht / Mail an den Administrator der Anwendung / des Frameworks senden.

Idealerweise sollten wir niemals Fehler in unserer Java-Anwendung finden, da es sich um einen anormalen Zustand handelt. Die Anwendung würde sich in einem abnormalen Zustand befinden und zu einem Carshing oder einem ernsthaften falschen Ergebnis führen.

Es könnte angebracht sein, Fehler in Komponententests zu erkennen, die eine Assertion überprüfen. Wenn jemand Behauptungen deaktiviert oder die Behauptung anderweitig löscht, möchten Sie es wissen

Es gibt einen Fehler, wenn die JVM nicht mehr wie erwartet funktioniert oder kurz davor ist. Wenn Sie einen Fehler feststellen, gibt es keine Garantie, dass der catch-Block ausgeführt wird, und noch weniger, dass er bis zum Ende ausgeführt wird.

Es hängt auch vom laufenden Computer ab, vom aktuellen Speicherzustand, also gibt es keine Möglichkeit zu testen, zu versuchen und Ihr Bestes zu geben. Sie werden nur ein hasserfülltes Ergebnis haben.

Sie werden auch die Lesbarkeit Ihres Codes herabstufen.