Mysteriöse Linie im Stack-Trace

8

Während Untersuchung einer Stack-Trace-Diskrepanz beim Verfassen einer anderen Antwort stieß ich auf ein Verhalten, das ich nicht verstehe. Betrachten Sie das folgende Testprogramm (das ist so weit unten, wie ich es eingrenzen könnte):

%Vor%

Die Zeilen 11 und 13 sind im obigen Snippet gekennzeichnet und können unter ideone ausgeführt werden. Die Ausgabe dieses Programms ist:

%Vor%

Meine Frage ist: Warum wird Zeile 11 im Stack für den zweiten und dritten Testfall nachverfolgt? Der Unterschied zwischen den drei Testfällen sind die deklarierten Typen von a und b .

Zeile 11 (die Klasse Deklarationszeile) ist nur unter den folgenden Bedingungen vorhanden:

  1. Wenn Test eine Schnittstelle implementiert und
  2. Wenn die Ausnahme von der Interface-Methode ausgelöst wird und
  3. Wenn die Schnittstelle einen Typparameter und
  4. verwendet
  5. Wenn der Typparameter der Klassendeklaration extends Test<T> enthält (Zeile 11 ist nicht enthalten, wenn sie als class Test<T> deklariert ist) und
  6. Wenn die Methode für den Typ TestInterface und nicht für den Typ Test aufgerufen wird.

Beachten Sie Folgendes:

  • Es wird definitiv meine Ausnahme ausgelöst (Nachrichten- und Stack-Trace).
  • Keine anderen Ausnahmen werden ausgelöst, wenn ich meine nicht werfe.
  • Ich habe dies mit dem Oracle JDK 1.7 und 1.8 unter Windows und 1.8 unter Idone reproduziert. 1.7 enthält jedoch ein Stack-Trace-Element in Zeile 1 anstelle von 11 (was doppelt seltsam ist).

Was passiert hier? Wie kommt es, dass diese Zeile im Stack-Trace endet und warum erscheint sie nicht, wenn beide Objekte als Test ? Deklariert sind?

Hier ist das ursprüngliche Programm, das dies ausgelöst hat , wobei Zeile 55 von java.lang.Enum vorhanden ist, wenn a als% co_de deklariert ist %, aber nicht vorhanden, wenn es als Comparable deklariert ist. Zeile 55 ist die Deklaration von Enum in der JDK-Quelle, Zeile 180 ist eine explizit geworfene Enum .

    
Jason C 26.02.2017, 03:41
quelle

1 Antwort

13

Sie betrachten die Auswirkungen einer Bridge-Methode !

>

Die in test deklarierte TestInterface -Methode löscht test(Object) , aber die in test deklarierte Test -Methode löscht test(Test) . Eine Methodensuche für die test(Object) -Methode findet die test(Test) -Methode nicht, also setzt Java tatsächlich separate Methoden test(Object) und test(Test) in Test 's Bytecode.

Ihre erste Testversion verwendet die Methode test(Test) , die sich wie erwartet verhält. Ihre anderen Versuche verwenden die Methode test(Object) , bei der es sich um eine synthetische Brückenmethode handelt, die nur die Methode test(Test) aufruft. Diese Bridge-Methode hat nicht wirklich eine Zeilennummer, daher wird sie in der Stack-Trace mit der ziemlich willkürlichen Zeilennummer von 11 angezeigt.

    
user2357112 26.02.2017, 03:57
quelle