Antworten:
Im Allgemeinen niemals.
Manchmal müssen Sie jedoch bestimmte Fehler abfangen.
Wenn Sie Framework-Code schreiben (Laden von Klassen von Drittanbietern), ist es möglicherweise ratsam, ihn abzufangen LinkageError
(keine Klassendefinition gefunden, unbefriedigter Link, inkompatibler Klassenwechsel).
Ich habe auch einige dumme Codes von Drittanbietern gesehen, die Unterklassen von werfen Error
, also müssen Sie auch damit umgehen.
Ich bin mir übrigens nicht sicher, ob es nicht möglich ist, sich davon zu erholen OutOfMemoryError
.
Noch nie. Sie können nie sicher sein, dass die Anwendung die nächste Codezeile ausführen kann. Wenn Sie eine erhalten OutOfMemoryError
, haben Sie keine Garantie dafür, dass Sie in der Lage sind, alles zuverlässig zu tun . Catch RuntimeException und aktivierte Ausnahmen, aber niemals Fehler.
boolean assertionsEnabled = false; assert assertionsEnabled = true;
Im Allgemeinen sollten Sie es immer abfangen java.lang.Error
und in ein Protokoll schreiben oder dem Benutzer anzeigen. Ich arbeite im Support und sehe täglich, dass Programmierer nicht sagen können, was in einem Programm passiert ist.
Wenn Sie einen Daemon-Thread haben, müssen Sie verhindern, dass dieser beendet wird. In anderen Fällen funktioniert Ihre Anwendung ordnungsgemäß.
Sie sollten nur java.lang.Error
auf höchstem Niveau fangen .
Wenn Sie sich die Liste der Fehler ansehen, werden Sie feststellen, dass die meisten Fehler behoben werden können. Beispielsweise ZipError
tritt beim Lesen beschädigter Zip-Dateien ein Fehler auf.
Die häufigsten Fehler sind OutOfMemoryError
und NoClassDefFoundError
, die in den meisten Fällen Laufzeitprobleme sind.
Beispielsweise:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
kann ein produzieren, OutOfMemoryError
aber es ist ein Laufzeitproblem und kein Grund, Ihr Programm zu beenden.
NoClassDefFoundError
treten meistens auf, wenn eine Bibliothek nicht vorhanden ist oder wenn Sie mit einer anderen Java-Version arbeiten. Wenn es ein optionaler Teil Ihres Programms ist, sollten Sie Ihr Programm nicht beenden.
Ich kann noch viele weitere Beispiele dafür nennen, warum es eine gute Idee ist, Throwable
auf höchster Ebene zu fangen und eine hilfreiche Fehlermeldung zu erstellen.
OutOfMemoryError
ist kein Laufzeitfehler. Es gibt keine Garantie dafür, dass die Anwendung ihn wiederherstellen kann. Wenn Sie Glück haben, erhalten Sie möglicherweise OOM, new byte[largeNumber]
aber wenn diese Zuordnung nicht ausreicht, um OOM zu verursachen, kann sie in der nächsten Zeile oder im nächsten Thread ausgelöst werden. Dies ist ein Laufzeitproblem, da length
nicht vertrauenswürdige Eingaben vor dem Aufruf überprüft werden sollten new byte[]
.
NoClassDefFoundError
kann überall auftreten , da es aufgerufen wird, wenn kompilierter Java-Code keine Klasse finden kann. Wenn Ihr JDK falsch konfiguriert ist, kann dies durch den Versuch ausgelöst werden, eine java.util.*
Klasse zu verwenden , und es ist praktisch unmöglich, dagegen zu programmieren. Wenn Sie optional eine Abhängigkeit einschließen, sollten Sie verwenden, um ClassLoader
zu überprüfen, ob sie existiert und welche ausgelöst wird ClassNotFoundException
.
ZipError
Gibt an, dass die JAR-Datei mit Klassen eine beschädigte Zip-Datei ist. Dies ist ein ziemlich ernstes Problem, und zu diesem Zeitpunkt können Sie keinem Code vertrauen, der ausgeführt wird, und es wäre unverantwortlich, wenn Sie versuchen würden, ihn "wiederherzustellen".
java.lang.Error
oder java.lang.Throwable
auf höchster Ebene zu versuchen, etwas damit zu tun - beispielsweise eine Fehlermeldung zu protokollieren. Zu diesem Zeitpunkt gibt es jedoch keine Garantie dafür, dass dies ausgeführt wird. Wenn Ihre JVM OOM-fähig ist, kann der Versuch, sich zu protokollieren, mehr String
s zuweisen, wodurch ein anderes OOM ausgelöst wird.
In einer Multithread-Umgebung möchten Sie es am häufigsten fangen! Wenn Sie es fangen, protokollieren Sie es und beenden Sie die gesamte Anwendung! Wenn Sie das nicht tun, ist ein Thread, der möglicherweise einen entscheidenden Teil leistet, tot, und der Rest der Anwendung wird denken, dass alles normal ist. Daraus können viele unerwünschte Situationen entstehen. Ein kleinstes Problem ist, dass Sie die Ursache des Problems nicht leicht finden können, wenn andere Threads einige Ausnahmen auslösen, weil ein Thread nicht funktioniert.
Zum Beispiel sollte eine Schleife normalerweise sein:
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
Selbst in einigen Fällen möchten Sie verschiedene Fehler unterschiedlich behandeln. In OutOfMemoryError können Sie beispielsweise die Anwendung regelmäßig schließen (möglicherweise sogar Speicher freigeben und fortfahren). In anderen Fällen können Sie nicht viel tun.
OutOfMemoryError
und fortzufahren, anstatt sofort zu existieren, da sich Ihr Programm dann in einem undefinierten Zustand befindet .
Ein Error
sollte normalerweise nicht gefangen werden , da dies auf einen abnormalen Zustand hinweist, der niemals auftreten sollte .
Aus der Java-API-Spezifikation für die Error
Klasse:
Eine
Error
UnterklasseThrowable
davon weist auf schwerwiegende Probleme hin, die eine vernünftige Anwendung nicht abfangen sollte. Die meisten dieser Fehler sind abnormale Zustände. [...]Eine Methode muss in ihrer Throws-Klausel keine Fehlerklassen deklarieren, die möglicherweise während der Ausführung der Methode ausgelöst, aber nicht abgefangen werden, da diese Fehler abnormale Bedingungen sind, die niemals auftreten sollten.
Wie in der Spezifikation erwähnt, wird ein Error
nur unter Umständen ausgelöst, bei denen Error
die Anwendung möglicherweise nur sehr wenig tun kann, und unter bestimmten Umständen befindet sich die Java Virtual Machine selbst möglicherweise in einem instabilen Zustand (zVirtualMachineError
)
Obwohl an Error
eine Unterklasse ist Throwable
, bedeutet dies, dass es von a gefangen werden kanntry-catch
Klausel , aber es wird wahrscheinlich nicht wirklich benötigt, da sich die Anwendung in einem abnormalen Zustand befindet, wenn einError
von der JVM ausgelöst wird.
Es gibt auch einen kurzen Abschnitt zu diesem Thema in Abschnitt 11.5 Die Ausnahmehierarchie der Java-Sprachspezifikation, 2. Ausgabe .
Und es gibt noch einige andere Fälle, in denen Sie einen Fehler erneut auslösen müssen, wenn Sie ihn feststellen . Zum Beispiel sollte ThreadDeath niemals abgefangen werden, es kann ein großes Problem verursachen, wenn Sie es in einer geschlossenen Umgebung (z. B. einem Anwendungsserver) abfangen:
Eine Anwendung sollte Instanzen dieser Klasse nur abfangen, wenn sie nach dem asynchronen Beenden bereinigt werden muss. Wenn ThreadDeath von einer Methode abgefangen wird, ist es wichtig, dass es erneut geworfen wird, damit der Thread tatsächlich stirbt.
Error
s fangen .
Sehr, sehr selten.
Ich habe es nur für einen sehr sehr spezifischen bekannten Fall getan. Beispielsweise könnte java.lang.UnsatisfiedLinkError ausgelöst werden, wenn zwei unabhängige ClassLoader dieselbe DLL laden. (Ich bin damit einverstanden, dass ich die JAR auf einen gemeinsam genutzten Klassenladeprogramm verschieben soll.)
Der häufigste Fall ist jedoch, dass Sie eine Protokollierung benötigen, um zu wissen, was passiert ist, wenn Benutzer sich beschweren. Sie möchten eine Nachricht oder ein Popup an den Benutzer, anstatt stillschweigend tot zu sein.
Selbst Programmierer in C / C ++ geben einen Fehler ein und sagen etwas, was die Leute nicht verstehen, bevor es beendet wird (z. B. Speicherfehler).
In einer Android-Anwendung fange ich einen java.lang.VerifyError ab . Eine Bibliothek, die ich verwende, funktioniert nicht auf Geräten mit einer alten Version des Betriebssystems, und der Bibliothekscode löst einen solchen Fehler aus. Ich könnte den Fehler natürlich vermeiden, indem ich zur Laufzeit die Version des Betriebssystems überprüfe, aber:
Idealerweise sollten wir keine Fehler behandeln / abfangen. Es kann jedoch Fälle geben, in denen dies aufgrund der Anforderungen an das Framework oder die Anwendung erforderlich ist. Angenommen, ich habe einen XML-Parser-Daemon, der den DOM-Parser implementiert, der mehr Speicher benötigt. Wenn es eine Anforderung gibt, wie der Parser-Thread beim Abrufen von OutOfMemoryError nicht beendet werden sollte , sollte er stattdessen damit umgehen und eine Nachricht / E-Mail an den Administrator der Anwendung / des Frameworks senden.
Es liegt ein Fehler vor, wenn die JVM nicht mehr wie erwartet funktioniert oder kurz davor steht. Wenn Sie einen Fehler abfangen, gibt es keine Garantie dafür, dass der catch-Block ausgeführt wird, und noch weniger, dass er bis zum Ende ausgeführt wird.
Dies hängt auch vom laufenden Computer und dem aktuellen Speicherstatus ab, sodass Sie nicht testen, versuchen und Ihr Bestes geben können. Sie werden nur ein hasardous Ergebnis haben.
Sie werden auch die Lesbarkeit Ihres Codes herabstufen.