Der Eclipse-Compiler erzeugt keinen solchen Ausnahmetabelleneintrag
Die JVM-Spezifikation dokumentiert keine Laufzeitausnahmen für das astore Anweisung.
Ich weiß, dass es legal ist, die JVM zu werfen VirtualMachineError für jede Anweisung. Ich denke, der eigenartige Eintrag verhindert, dass sich solche Fehler aus dieser Anweisung ausbreiten.
Ich werde dies als Kommentar posten, da ich es nicht geschafft habe, mich um dieses Konzept zu kümmern. Zu diesem Thema gibt es einen Eintrag, warum der letzte Eintrag bei generiert wird ein Blog. Anscheinend ist das Verhalten des Compilers zum Kompilieren des finally-Blocks, wie in der VM-Spezifikation angegeben, etwas daneben, was den Sun/Oracle-Compiler betrifft. Der letzte Ausnahmetabelleneintrag ist vorhanden, um den “erzeugten Ausnahmehandler” zu schützen. Ich habe nicht herausgefunden, wie die Wache funktioniert und warum sie so funktionieren sollte.
– Vineet Reynolds
17. Juni 2011 um 15:43 Uhr
Dafür gibt es nur zwei mögliche Erklärungen: Der Compiler enthält einen Fehler oder er setzt aus obskuren Gründen eine Art Wasserzeichen.
Dieser Eintrag ist sicherlich falsch, da jede Ausnahme, die von einem finally-Block selbst ausgelöst wird, den Ausführungsfluss an den äußeren Ausnahmehandler oder den finally-Block senden muss, aber niemals den gleichen finally-Block “erneut ausführen” muss.
Ein guter Beweis dafür, dass es sich um einen Fehler/ein Wasserzeichen handelt, ist auch die Tatsache, dass Eclipse (und vielleicht andere Java-Compiler) keinen solchen Eintrag generieren, und trotzdem funktionieren von Eclipse generierte Klassen auf Suns JVM einwandfrei.
Dieser Beitrag ist jedoch interessant, da die Klassendatei anscheinend gültig und verifiziert ist. Wenn ich ein JVM-Implementierer wäre, würde ich diesen Eintrag ignorieren und einen Fehler für Sun/Oracle füllen!
“Jede Ausnahme, die von einem finally-Block selbst ausgelöst wird, muss den Ausführungsfluss an den äußeren Ausnahmehandler senden” — Nein, nicht, wenn Sie einen inneren Catch-Block haben. Außerdem verwechseln Sie Java mit Bytecode: Das Bytecode-Programm sollte die Semantik des zu kompilierenden Java-Programms implementieren. Es kann dies tun, indem es alle wirft / fängt Arten von verrückten Ausnahmen. Es gibt keinen “richtigen” oder “falschen” Weg, das Programm zu kompilieren. Mein Verdacht ist, dass der Eintrag ein Nebeneffekt eines allgemeineren Konstrukts im Compiler ist. Vielleicht wird ein solcher Eintrag sogar vom ausgegeben Eclipse-Compiler in einigen seltenen Ausnahmefällen.
– aiobe
20. Juni 2011 um 18:45 Uhr
@aioobe Während JVM anstelle von Java ein Ziel für andere Sprachen sein kann, zeigt diese Frage explizit, dass ein Java-Programm für JVM kompiliert wird. Die JVM kann zulassen, dass eine Ausnahme von genau dem Code behandelt wird, der sie ausgelöst hat, aber eine store_2-Anweisung gehört zu einem Java-finally-Block, der keinen inneren Versuch hat, sodass jede von ihr ausgelöste Ausnahme den Ausführungsfluss tatsächlich an einen äußeren Ausnahmehandler senden muss. “Mein Verdacht ist, dass der Eintrag ein Nebeneffekt eines allgemeineren Konstrukts im Compiler ist.” – Das denke ich auch, aber trotzdem bricht dies den Java-Sprachvertrag.
– Fernakolo
20. Juni 2011 um 19:36 Uhr
dies bricht den Java-Sprachvertrag – Nein, tut es nicht. Sie könnten zum Beispiel so argumentieren: Jede Ausnahme, die von einer Anweisung innerhalb der finally-Klausel ausgelöst wird, sollte aus der Klausel heraus propagiert werden. Wenn also keine Anweisungen in der finally-Klausel vorhanden sind, können von dort keine Ausnahmen propagiert werden. Daher ist es völlig legal, alle Ausnahmen im “kompilierten finally-Block” zu unterdrücken, wenn der kompilierte Block keine Anweisungen enthielt.
– aiobe
20. Juni 2011 um 19:47 Uhr
@aioobe Ja, aber der betreffende finally-Block enthält Anweisungen !!! Eine andere Möglichkeit, zu erklären, warum es sich um einen Fehler handelt: Wenn eine JVM einen VirtualMachineError (oder eine andere Fehlerausnahme) auf die astore_2-Funktion auslöst, kann sie in eine Endlosschleife eintreten, die 100 % einer CPU verbraucht, selbst ohne Schleife im Java-Code, wenn kompiliert mit Javac. Wenn jetzt dieselbe Klasse mit Eclipse kompiliert wurde, sendet der VirtualMachineError den Ausführungsfluss korrekt nach außen.
– Fernakolo
20. Juni 2011 um 19:48 Uhr
“Der betreffende finally-Block enthält keine Anweisungen” — Richtig. Das ist genau der Grund, warum es eigentlich in Ordnung ist, alle Ausnahmen zu unterdrücken, die vom Bytecode ausgelöst werden, der dem No-Statement-Block entspricht. Bezüglich des VirtualMachineError: Dann ist diese Ausnahme auf einen Fehler in der JVM, dh der JVM, zurückzuführen hat den Vertrag gebrochen, bevor die Ausnahme überhaupt erfasst wurde.
– aiobe
20. Juni 2011 um 19:50 Uhr
Dan Cruz
Wenn ich mir den Quellcode von OpenJDK 7 ansehe, würde ich es wagen, den Grund dafür zu erraten 28 29 28 any Ausnahmetabelleneintrag liegt daran, dass der Code, der die verarbeitet astore Bytecode (vgl Code ab Zeile 1871) kann ein werfen java.lang.LinkageError Ausnahme, wenn der entnommene Wert aus dem Operandenstapel nicht a ist returnAddress oder reference type (siehe die Java Virtual Machine Specification für ein Laden) und sie möchten, dass diese Fehlerbedingung im Stack-Trace angezeigt wird.
Für den Fall, dass der Operandenstapel einen fehlerhaften Operandentyp enthält, löscht die JVM den Operandenstapel (um diesen fehlerhaften Operanden loszuwerden), fügen Sie a LinkageError
auf dem Operandenstapel und führen Sie die aus astore Bytecode erneut, diesmal erfolgreich ausgeführt astore Bytecode mit einer bereitgestellten JVM LinkageError
Objektbezug. Siehe die werfen Dokumentation für weitere Informationen.
Ich würde stark die Ursache für das Werfen a vermuten LinkageError während astore Die Verarbeitung erfolgt aufgrund der Komplexitäten JSR/RET-Subroutinen Einführung in die Bytecode-Überprüfung (OpenJDK-Änderungen 6878713, 6932496 und 7020373 sind neuere Beweise dafür JSRdie anhaltende Komplexität von ; Ich bin sicher, dass Sun/Oracle andere Closed-Source-Tests hat, die wir in OpenJDK nicht sehen). Das OpenJDK 7020373 Nutzungen ändern LinkageError um Testergebnisse zu validieren/ungültig zu machen.
Hmm .. würde ein solcher Typfehler nicht im Bytecode-Überprüfungsschritt abgefangen werden? (Vor dem Ausführen des Codes.)
– aiobe
29. September 2011 um 19:23 Uhr
Meine Antwort wurde mit Informationen zur Komplexität der JSR/RET-Unterroutine aktualisiert, was die Bytecode-Überprüfung schmerzhaft macht.
– Dan Cruz
30. September 2011 um 13:10 Uhr
Mein Verständnis ist, dass der zweite Eintrag in der Ausnahmetabelle die implizite Catch-Everything-Klausel ist, die vom Compiler hinzugefügt wurde, um alle Ausnahmen/Fehler abzudecken, die im Hauptteil oder in den Catch-Handlern ausgelöst werden, und der dritte Eintrag der Wächter für diesen impliziten Catch ist, um den Fluss zu erzwingen durch die endlich Hinrichtung.
10265400cookie-checkSeltsamer Ausnahmetabelleneintrag, der von Javac von Sun erzeugt wurdeyes
Ich werde dies als Kommentar posten, da ich es nicht geschafft habe, mich um dieses Konzept zu kümmern. Zu diesem Thema gibt es einen Eintrag, warum der letzte Eintrag bei generiert wird ein Blog. Anscheinend ist das Verhalten des Compilers zum Kompilieren des finally-Blocks, wie in der VM-Spezifikation angegeben, etwas daneben, was den Sun/Oracle-Compiler betrifft. Der letzte Ausnahmetabelleneintrag ist vorhanden, um den “erzeugten Ausnahmehandler” zu schützen. Ich habe nicht herausgefunden, wie die Wache funktioniert und warum sie so funktionieren sollte.
– Vineet Reynolds
17. Juni 2011 um 15:43 Uhr