Nach meinem Verständnis ist throw
ein primativer jvm-Befehl. Wenn dies aufgerufen wird, prüft die JVM, ob der aktuelle Aufrufstapel sie abfangen kann. wenn es nicht möglich ist, dann öffnet java den Call-Stack fast genau so, als ob eine Rückgabe aufgerufen würde. dann prüft der jvm ", ob der aktuelle Aufruf-Stack ihn abfangen kann" und so weiter.
Meine Frage: Wie ist es algorithmisch möglich, dass die JVM weiß, wo im Call-Stack eine bestimmte Ausnahme auftreten kann? Sind in jedem Call-Stack-Eintrag Metadaten gespeichert, die Ausnahmen zu Code-Blöcken zuordnen? Gibt es eine statische Datenstruktur im Heap, die das irgendwie verfolgt? weil da irgendwo Daten sein müssen, die das verfolgen.
Die JVM-Spezifikation enthält Einzelheiten dazu.
Insbesondere Abschnitt 4.7.3 gibt Details über die Ausnahmetabelle an, bei der es sich um eine Reihe von Einträgen handelt, die angeben, welche Ausnahmen zwischen welchen Anweisungen gefangen werden. Abschnitt 3.12 gibt ein konkretes Beispiel dafür.
Wie diese Metadaten in nativen Code für das JIT abgebildet werden, ist natürlich eine andere Sache - und umsetzungsspezifisch. Zum Beispiel könnte es eine Rückverknüpfung von jeder Befehlsstelle in dem nativen JIT-Code zurück zu dem ursprünglichen Bytecode-Ort geben, an welchem Punkt die Ausnahmetabelle konsultiert werden kann, um den richtigen Handler zu finden.
Allgemein gesprochen: Wenn eine Ausnahme ausgelöst wird, extrahiert die JVM den "Aufruf-Stack". Dies identifiziert, welcher Bytecode oder Maschinenbefehl auf jeder Ebene in dem Aufrufstapel ausgeführt wurde, zusammen mit der Klasse und der Methode, die diesem Ort zugeordnet sind.
Dann sucht die JVM für jede Methode im Stapel (beginnend mit der Methode, bei der die Ausnahme aufgetreten ist und rückwärts arbeitet) (in dem internen Klassenobjekt) bei der Tabellenzuordnung von try / catch-Bereichen zu Bytecode- / Maschinenbefehlsbereichen .
Wenn ein "match" in der Tabelle für eine Methode gefunden wird und der Typ der ausgelösten Ausnahme eine Klasse ist, auf die im gefundenen Bereich überwacht wird, wird die Steuerung nach dem Setzen des Wertes an den Einstiegspunkt catch
übergeben Ausnahme in eine Art von Parameter-Speicherort, so dass die catch
-Klausel darauf verweisen kann.
Wenn eine "Übereinstimmung" in der Tabelle nicht gefunden wird, wird der Aufrufstapel effektiv "geupdated", wobei die nächste frühere Methode oben auf dem Stapel platziert wird, und die obige Suche nach einer "Übereinstimmung" in der Tabelle der früheren Methode Versuch / Fangbereiche wird wiederholt.
Dies ist natürlich eine übermäßige Vereinfachung. Es gibt eine Menge zusätzlicher Logik, die bei der Behandlung von finally
range involviert ist, z. B. und mehrere "Kanten" -Fälle.
Tags und Links java exception-handling exception jvm stack-unwinding