Frage: Ist die Ausnahmebehandlung in Java wirklich langsam?
Konventionelle Weisheit und auch viele Google-Ergebnisse besagen, dass außergewöhnliche Logik nicht für den normalen Programmablauf in Java verwendet werden sollte. Dafür werden in der Regel zwei Gründe genannt,
- er ist wirklich langsam - sogar um eine Größenordnung langsamer als normaler Code (die angegebenen Gründe sind unterschiedlich),
y
- es ist chaotisch, weil die Leute erwarten, dass nur Fehler in außergewöhnlichem Code behandelt werden.
Diese Frage bezieht sich auf die Nummer 1.
Ein Beispiel, diese Seite beschreibt die Java-Ausnahmebehandlung als "sehr langsam" und bezieht die Langsamkeit auf die Erstellung der Ausnahmemeldungszeichenfolge - "diese Zeichenfolge wird dann bei der Erstellung des Ausnahmeobjekts verwendet, das ausgelöst wird. Das ist nicht schnell." Der Artikel Effektive Ausnahmebehandlung in Java sagt, dass "der Grund dafür in dem Aspekt der Objekterzeugung bei der Ausnahmebehandlung liegt, der das Auslösen von Ausnahmen von Natur aus langsam macht". Ein anderer Grund ist, dass die Stack-Trace-Generierung die Ursache für die Verlangsamung ist.
Meine Tests (mit Java 1.6.0_07, Java HotSpot 10.0, auf 32-Bit-Linux) zeigen, dass die Ausnahmebehandlung nicht langsamer ist als normaler Code. Ich habe versucht, eine Methode in einer Schleife auszuführen, die einen Code ausführt. Am Ende der Methode verwende ich einen Booleschen Wert, um anzugeben, ob return o werfen . Auf diese Weise ist die tatsächliche Verarbeitung die gleiche. Ich habe versucht, die Methoden in verschiedenen Reihenfolgen auszuführen und den Durchschnitt meiner Testzeiten zu ermitteln, weil ich dachte, dass die JVM sich aufwärmen könnte. In allen meinen Tests war der Wurf mindestens so schnell wie die Rückkehr, wenn nicht sogar schneller (bis zu 3,1 % schneller). Ich bin völlig offen für die Möglichkeit, dass meine Tests falsch waren, aber ich habe in den letzten ein oder zwei Jahren nichts in Form von Codebeispielen, Testvergleichen oder Ergebnissen gesehen, die zeigen, dass die Ausnahmebehandlung in Java tatsächlich langsam ist.
Was mich auf diesen Weg geführt hat, war eine API, die ich verwenden musste und die Ausnahmen als Teil der normalen Steuerungslogik auslöste. Ich wollte sie in ihrer Verwendung korrigieren, aber jetzt kann ich das vielleicht nicht mehr. Werde ich sie stattdessen für ihr vorausschauendes Denken loben müssen?
In dem Papier Effiziente Java-Ausnahmebehandlung bei der Just-in-Time-Kompilierung Die Autoren weisen darauf hin, dass das Vorhandensein von Ausnahmebehandlungsroutinen allein, auch wenn keine Ausnahmen ausgelöst werden, ausreicht, um den JIT-Compiler daran zu hindern, den Code ordnungsgemäß zu optimieren und ihn somit zu verlangsamen. Ich habe diese Theorie noch nicht getestet.
13 Stimmen
Ich weiß, dass Sie nicht nach 2) gefragt haben, aber Sie sollten wirklich erkennen, dass die Verwendung einer Ausnahme für den Programmablauf nicht besser ist als die Verwendung von GOTOs. Einige Leute verteidigen Gotos, andere würden das verteidigen, wovon Sie sprechen, aber wenn Sie jemanden fragen, der beides über einen längeren Zeitraum implementiert und gewartet hat, wird er Ihnen sagen, dass beides schlechte, schwer zu wartende Entwurfspraktiken sind (und er wird wahrscheinlich den Namen der Person verfluchen, die dachte, sie sei klug genug, um die Entscheidung zu treffen, sie zu verwenden).
98 Stimmen
Bill, die Behauptung, die Verwendung von Ausnahmen für den Programmablauf sei nicht besser als die Verwendung von GOTOs, ist nicht besser als die Behauptung, die Verwendung von Konditionalen und Schleifen für den Programmablauf sei nicht besser als die Verwendung von GOTOs. Das ist ein Ablenkungsmanöver. Erkläre dich selbst. Ausnahmen können und werden in anderen Sprachen effektiv für den Programmfluss verwendet. Idiomatischer Python-Code verwendet zum Beispiel regelmäßig Ausnahmen. Ich kann und habe Code gepflegt, der Ausnahmen auf diese Weise verwendet (allerdings nicht in Java), und ich glaube nicht, dass daran etwas grundsätzlich falsch ist.
5 Stimmen
Beachten Sie, dass einige Web-Frameworks Exceptions als bequeme Möglichkeit zur Umleitung verwenden - z.B. Wicket's RestartResponseException . Es passiert nur wenige Male pro Anfrage, normalerweise nicht, und ich kann mir kaum einen bequemeren Weg in einem Java-orientierten Komponenten-Framework vorstellen.
24 Stimmen
@mmalone Ausnahmen für den normalen Kontrollfluss zu verwenden, ist in Java eine schlechte Idee, weil die Wahl des Paradigmas wurde auf diese Weise getroffen . Lesen Sie Bloch EJ2 - er sagt eindeutig, dass, Zitat, (Punkt 57)
exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow
- mit einer vollständigen und ausführlichen Erklärung, warum. Und er war derjenige, der schrieb Java lib. Daher ist er derjenige, der den API-Vertrag der Klassen definiert. /Stimme Bill K in diesem Punkt zu.8 Stimmen
@OndraŽižka Wenn ein Framework dies tut (Verwendung von Exceptions unter nicht außergewöhnlichen Bedingungen), ist es fehlerhaft und vom Design her gebrochen und bricht den Vertrag der Exception-Klasse der Sprache. Nur weil einige Leute lausigen Code schreiben, ist er nicht weniger lausig.
7 Stimmen
Btw, es beunruhigt mich sehr, dass der Kommentar von mmalone so viele "upvotes" bekommen hat, obwohl er sagte: "Ich glaube nicht, dass daran etwas grundsätzlich falsch ist"... Ich verstehe zwar die Bitte um einen Verweis, die er geäußert hat (obwohl der Verweis in diesem Fall ziemlich offensichtlich ist), aber es macht mich traurig zu sehen, wie viele Leute dem zustimmen, da es für mich nur unterstreicht, wie sehr sich die SO "Qualitätssicherung der Gemeinschaft" im Laufe der Zeit verschlechtert hat.
2 Stimmen
Kein Geringerer als der Schöpfer von stackoverflow.com hat zu Protokoll gegeben, dass Ausnahmen schlimmer sind als GOTOs: joelonsoftware.com/artikel/2003/10/13.html
11 Stimmen
Kein anderer als der Schöpfer von stackoverflow.com irrt sich bei Ausnahmen. Die goldene Regel der Softwareentwicklung lautet: Mache niemals das Einfache komplex und unhandlich. Er schreibt: "Es ist wahr, dass ein einfaches 3-zeiliges Programm oft auf 48 Zeilen anwächst, wenn man eine gute Fehlerprüfung einbaut, aber so ist das Leben, ..." Dies ist eine Suche nach Reinheit, nicht nach Einfachheit.
0 Stimmen
Eines der lustigen Dinge an Java - wir machen uns Gedanken über so etwas wie die Leistung von try/catch, die Java um einen RIESIGEN Faktor verlangsamt - aber es wäre immer noch schneller als fast jede andere Sprache da draußen (abgesehen von C und ein paar esoterischen Sprachen wie Fortran!?!). Selbst wenn Sie viel mit Ausnahmen arbeiten würden, würden Sie nicht auf die Geschwindigkeit von Python herunterkommen; und was Ruby angeht??? Nicht einmal, wenn jede einzelne Anweisung irgendwie ausnahmebasiert wäre, könnte man so langsam werden. Andererseits führen Ausnahmen zu schwer nachvollziehbarem Code und sind generell eine PITA, die man am besten vermeiden sollte, wo immer es möglich ist.
0 Stimmen
Früher war das Auffüllen der Stacktrace ziemlich langsam. Meinem Verständnis nach verbesserte sich dies drastisch um Java 5-6-ish
0 Stimmen
Der Operator sollte einige Tests durchführen, nachdem er tausend Frames auf den Stack geschoben hat, damit die Auswirkungen eines größeren Stacktraces deutlicher werden.
0 Stimmen
Die Frage bezieht sich auf die "Behandlung" von Ausnahmen, bei denen die Alternative sehr oft ein Absturz ist. Viel langsamer als angehalten kann man nicht werden. Wenn Sie Ausnahmen als Element der Ablaufsteuerung verwenden wollen, wie Bill K. vorschlug, stellen Sie einfach sicher, dass niemand sonst den Code pflegen muss...