Ausnahme

Mit Ausnahme (engl. Exception) bezeichnet man eine Klasse von Fehlern, die während der Laufzeit auftreten. Sofern für diese Fälle keinerlei softwaretechnische Maßnahmen getroffen werden, führt das häufig zum Absturz des gesamten Software-Systems. Aber auch andere ungewöhnliche Situationen können durch eine gezielte Ausnahmebehandlung (Exception Handling) aufgefangen und sogar gelöst werden, so dass daran anschließend das Programm weiterhin ausgeführt werden kann.


Die konzeptionelle Basis der Ausnahmebehandlung berücksichtigt, dass eine Situation in einer Funktion auf niedriger Ebene eine Ausnahme erzeugt, diese über die aufrufenden Ebenen weitergegeben wird und letztendlich von einem Stück Programmcode - dem sogenannten Exception Handler - zentral bearbeitet wird. Für die Behandlung von Ausnahmen stellen die meisten Programmiersprachen wie u.a. C++, C#, Java, Eiffel, Ada, Python, Ruby, Delphi oder Scala entsprechende Mechanismen standardmäßig zur Verfügung.

In einem Programm oder der Laufzeitumgebung wie beispielsweise dem Java Runtime Environment (JRE) können während der Laufzeit Situationen auftreten, die allgemein als Laufzeitfehler bezeichnet werden und zu einer Ausnahme führen. Dabei können diese Situationen verschiedenste Ursachen haben wie beispielsweise die Eingabe unzulässiger Werte, eine unerlaubte Division durch Null, eine instabile Netzwerkverbindung, dem Drucker fehlt bei gegebenem Druckauftrag das Papier oder das Öffnen einer nicht vorhandenen Datei.

All diesen Situationen ist eines gemeinsam: Sofern der Fehler nicht behandelt wird, führen sie zum Abbruch des Programms. Situationen dieser Art werden als Exceptions bezeichnet, und müssen schon im Verlauf der Software-Entwicklung erkannt und behandelt werden. Die Zielsetzung dieser Fehlerbehandlung ist es, dem Anwender eines Programms beispielsweise durch eine Korrektur seiner Eingabe die Fortsetzung des Programms zu ermöglichen oder im extremen Fall das Programm, nach Sicherung aller notwendigen Daten, zu beenden. Diese Form der Fehlerbehandlung bezeichnet man auch als Strukturierte Ausnahmebehandlung (engl. Structured Exception Handling).

Laufzeitfehler und Fehlerobjekte

Ein Laufzeitfehler erzeugt bei seinem Auftreten ein Fehlerobjekt, welches die Einzelheiten über den entstandenen Fehler kapselt. Dieses Objekt sucht innerhalb der Laufzeitumgebung nach einem Exception Handler, der wiederum das Fehlerobjekt aufnimmt und für dessen Behandlung entsprechend der Anforderungen durch die jeweilige Anwendung Sorge trägt. Die Ausnahme kann dabei entweder vom ursächlichen Teil des Programms direkt behandelt oder weitergeleitet werden. Der Empfänger des Fehlerobjektes kann dieses dann auch wieder entweder behandeln oder weiterleiten an die darüber liegende Ebene. Wenn eine Exception von keiner der aufgerufenen Methoden behandelt wird, wird die Software in einem nicht definierten Zustand beendet.

Die verschiedenen Programmiersprachen unterstützen gleichartige Konzepte zum Exception Handling. In Delphi kann eine Exception beispielsweise so wie in der Darstellung gehandhabt werden.

Exception in Delphi

Exception in Delphi

Die Anweisungen, die potentiell eine Exception verursachen können, werden in einem try-Block isoliert. Sofern kein Laufzeitfehler auftritt, werden die Anweisungen im try-Block wie definiert ausgeführt, und das Programm setzt sich dann hinter dem expect-Block fort. Sofern eine der Anweisungen des try-Blocks zu Laufzeitfehlern führt, wird der try-Block sofort beendet und es werden zunächst die Anweisungen im expect-Block ausgeführt und danach erst wieder der definierte Ablauf des Programms fortgesetzt.

Im Folgenden werden die Konzepte zur Ausnahmebehandlung mit Exceptions am Beispiel der Programmiersprache Java näher erläutert, da man diesbezüglich gut die Möglichkeiten des Exceptions Handlings generell nachvollziehen kann.

Eine Exception kann durch die Laufzeitumgebung oder Software-gesteuert durch den Entwickler der Software ausgelöst werden. An bestimmten Stellen in der Software erwartet auch schon der Compiler, dass eine Ausnahmebehandlung explizit programmiert wird. Dabei wird das Auslösen einer Exception als "Werfen" bezeichnet und deren Behandlung "Auffangen" genannt. Nur innerhalb einer Methode werden Exceptions geworfen. Java bietet folgende Konstrukte im Zusammenhang mit Exceptions:

try. Definiert einen Block, innerhalb welchem Ausnahmen auftreten können.

catch. Definiert einen Block, der die Behandlung der Ausnahmen durchführt.

finally. Definiert einen Block, der abschließende Arbeiten durchführt.

throw. Erzeugt Software-gesteuert eine Ausnahme.

throws. Deklariert, welche Ausnahme durch eine Methode ausgelöst werden kann.

Beispiel für Java-Konstrukte mit Exceptions

Beispiel für Java-Konstrukte mit Exceptions

Durch den Compiler wird in diesem Beispiel festgestellt, ob eine Behandlung für die Ausnahme NumberFormatException erfolgt ist: Durch die Aufnahme der Exceptions in den Methodenkopf überprüft der Compiler, ob alle Ausnahmen behandelt werden. Das ist beispielsweise in Java anders als in C++.

In Java wird eine Hierarchie von Klassen für Exceptions realisiert, und eine Exception ist immer ein Objekt dieser Klassen. Die Abbildung verdeutlicht den Aufbau dieser Hierarchie. Dabei werden die von der Java Virtual Machine (JVM) direkt generierten Ausnahmen beispielsweise OutOfMemoryExpection oder NullPointerExpection durch die Superklasse aller Fehlerklassen Throwable behandelt. Exceptions werden in kontrollierte und unkontrollierte Exceptions unterschieden, wobei unkontrollierte Exceptions nicht durch den Software-Entwickler abgefangen werden müssen. Die in Abbildung gezeigten Ausnahmen vom Typ Error und RuntimeException sind unkontrollierte Exceptions, alle anderen ordnet man den kontrollierten Exceptions zu, die durch den Software-Entwickler selbst behandelt werden müssen, andernfalls meldet bereits der Compiler einen Fehler. Die Fehlerursache für Exceptions des Typs Error sind ursächlich in der JVM begründet, während RuntimeException durch sorgfältige Programmierung auszuschließen sind. Die Dokumentation von Java gibt - wie in obigem Beispiel hinsichtlich der methode parseint() gezeigt - vor, welche Exception eine Methode auslösen kann.

Das Konzept von Java sieht die Definition eigener Ausnahmeklassen vor. Dabei leitet man eine Klasse von Exception oder eine Unterklasse von Exception ab, die dann anschließend sowie wie alle vordefinierten Exception-Klassen verwendet werden kann:

Class MyException extends Exception {};

Java hat beispielsweise die Möglichkeit, Exceptions in einem Programm nach einem festgelegten Mechanismus weiterzugeben. Dabei teilt die weitergebende Methode dem Compiler mit, dass die Exception auftreten kann, aber von dieser Methode nicht abgefangen wird.

Klassenhierarchie 
   der Exceptions

Klassenhierarchie der Exceptions

Eine interessante Methode ist getStackTrace(), die der Superklasse Throwable angehört. Darüber ist der Zugriff auf Elemente des Stacks möglich, was eine differenzierte Analyse von Fehlern möglich macht, da so die Reihenfolge der Aufrufe aller Methoden bis zur Ausnahme auf der Standardkonsole zur Verfügung gestellt werden. Weitere Informationen zu ausgelösten Exceptions bieten die Methoden getMessage() und toString() von Throwable. Dabei liefert getMessage() einen ausführlichen Meldungsstring zur Exception und toString() zusätzlich den Klassennamen.

Informationen zum Artikel
Deutsch: Ausnahme
Englisch: exception
Veröffentlicht: 27.10.2013
Wörter: 1007
Tags: #Software-Technologien
Links: Abbruch, Absturz, Ada, Anweisung, C++