Was kann java.lang.reflect.InvocationTargetException verursachen?


313

Nun, ich habe versucht zu verstehen und zu lesen, was es verursachen könnte, aber ich kann es einfach nicht verstehen:

Ich habe das irgendwo in meinem Code:

 try{
 ..
 m.invoke(testObject);
 ..
 } catch(AssertionError e){
 ...
 } catch(Exception e){
 ..
 }

Die Sache ist, dass, wenn es versucht, eine Methode aufzurufen, es InvocationTargetExceptionanstelle einer anderen erwarteten Ausnahme (speziell ArrayIndexOutOfBoundsException) auslöst . Da ich tatsächlich weiß, welche Methode aufgerufen wird, ging ich direkt zu diesem Methodencode und fügte einen Try-Catch-Block für die Zeile hinzu, die geworfen werden soll, ArrayIndexOutOfBoundsExceptionund er warf wirklich ArrayIndexOutOfBoundsExceptionwie erwartet. Doch wenn es hochgeht, ändert es sich irgendwie zu InvocationTargetExceptionund im obigen Code. catch(Exception e) E ist InvocationTargetExceptionund nicht ArrayIndexOutOfBoundsException wie erwartet.

Was könnte ein solches Verhalten verursachen oder wie kann ich so etwas überprüfen?

Antworten:


333

Sie haben eine zusätzliche Abstraktionsebene hinzugefügt, indem Sie die Methode mit Reflektion aufrufen. Die Reflektionsebene umschließt jede Ausnahme mit einer InvocationTargetException, mit der Sie den Unterschied zwischen einer Ausnahme, die tatsächlich durch einen Fehler im Reflektionsaufruf verursacht wurde (möglicherweise war Ihre Argumentliste beispielsweise nicht gültig), und einem Fehler innerhalb der aufgerufenen Methode erkennen können.

Packen InvocationTargetExceptionSie einfach die Ursache in der aus und Sie gelangen zur ursprünglichen.


4
@ user550413: Natürlich durch Auspacken der Ausnahme und Untersuchen. Sie können es jederzeit selbst werfen und auf diese Weise fangen, wenn Sie müssen.
Jon Skeet

157
Für alle, die sich fragen, was es bedeutet, "die Ursache innerhalb des zu entpacken InvocationTargetException", habe ich gerade festgestellt, dass Sie, wenn Sie es mit drucken lassen exception.printStackTrace(), nur den Abschnitt "Verursacht durch:" anstelle der oberen Hälfte / des normalen Abschnitts betrachten.
Januar

31
Um die Erklärung zum "Entpacken" hinzuzufügen, können Sie auch die Ausnahme abfangen und die Methode getCause () verwenden, die bei Bedarf auch erneut ausgelöst werden kann. So etwas wie try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }oder...catch... { throw ex.getCause() }
jcadcell

4
+1 @HJanrs für you just look at the "Caused By:" section instead of the top half/normal section
GingerHead

1
@DheraajBhaskar Bearbeiten Sie die Antworten anderer Personen nicht so, als wären sie Ihre eigenen, und verwenden Sie keine Anführungszeichenformatierung für Text, der nicht in Anführungszeichen steht. Diese Bearbeitung sollte als Kommentar veröffentlicht worden sein.
Marquis von Lorne

51

Die Ausnahme wird ausgelöst, wenn

InvocationTargetException - wenn die zugrunde liegende Methode eine Ausnahme auslöst.

Wenn also die Methode, die mit der Reflection-API aufgerufen wurde, eine Ausnahme auslöst (z. B. Laufzeitausnahme), wird die Exception von der Reflection-API in eine eingeschlossen InvocationTargetException.


tolle Erklärung!
Gaurav

Was ist, wenn ich erwarte, dass die zugrunde liegende Methode eine Ausnahme auslöst? Soll ich diese Ausnahme abfangen und einfach neu werfen?
jDub9

46

Verwenden Sie die getCause()Methode auf InvocationTargetException, um die ursprüngliche Ausnahme abzurufen.


21

Aus dem Javadoc von Method.invoke ()

Auslöser: InvocationTargetException - wenn die zugrunde liegende Methode eine Ausnahme auslöst.

Diese Ausnahme wird ausgelöst, wenn die aufgerufene Methode eine Ausnahme ausgelöst hat.


Stellen Sie sich vor, ich habe eine Kaskade von java.lang.reflect.ProxyInstanzen, die ein verpacktes Objekt erweitern. Jeder Proxybehandelt eine bestimmte Ausnahme (möglicherweise vom umschlossenen Objekt ausgelöst) ordnungsgemäß, indem er seine eigene verwendet InvocationHandler. Damit eine Ausnahme diese Kaskade durchläuft, bis der richtige Aufrufhandler / Proxy erreicht ist InvocationHandler, würde ich sie abfangen InvocationTargetException, auspacken und prüfen, ob die umschlossene Ausnahme instanceofdie Ausnahme ist, die von dieser behandelt wird InvocationHandler. Wenn es keine ist instanceof, würde ich die ausgepackte Ausnahme auslösen ... richtig?
Abdull

Ich würde immer die ausgepackte Ausnahme werfen.
Peter Lawrey

9

Das InvocationTargetExceptionist wahrscheinlich Ihr Abschluss ArrayIndexOutOfBoundsException. Bei der Verwendung von Reflexion lässt sich nicht im Voraus sagen, was diese Methode bewirken kann. Anstatt einen throws ExceptionAnsatz zu verwenden, werden alle Ausnahmen abgefangen und eingepackt InvocationTargetException.


Danke, aber wie werde ich mich zum Beispiel zwischen (AssertionError e) und (Exception e) unterscheiden? Wenn ich immer zuerst InvocationTargetException erhalte, bevor ich die Ursache entpacke, wo werde ich mich zwischen den einzelnen Ausnahmen unterscheiden?
user550413

9

Dadurch wird die genaue Codezeile in der spezifischen Methode gedruckt, die beim Aufrufen die Ausnahme auslöste:

try {

    // try code
    ..
    m.invoke(testObject);
    ..

} catch (InvocationTargetException e) {

    // Answer:
    e.getCause().printStackTrace();
} catch (Exception e) {

    // generic exception handling
    e.printStackTrace();
}

1
Vielen Dank; Dies hat mir geholfen zu erkennen, dass mein Problem nicht in der Reflexion selbst lag, sondern in der aufgerufenen Methode.
Jose Gómez

3

Dies beschreibt so etwas wie

InvocationTargetException ist eine aktivierte Ausnahme, die eine von einer aufgerufenen Methode oder einem aufgerufenen Konstruktor ausgelöste Ausnahme umschließt. Ab Version 1.4 wurde diese Ausnahme nachgerüstet, um dem allgemeinen Ausnahmekettenmechanismus für Ausnahmen zu entsprechen. Die "Zielausnahme", die zur Erstellungszeit bereitgestellt wird und auf die über die Methode getTargetException () zugegriffen wird, wird jetzt als Ursache bezeichnet und kann über die Methode Throwable.getCause () sowie die oben genannte "Legacy-Methode" aufgerufen werden.


2

Sie können mit der ursprünglichen Ausnahmeklasse mit der folgenden Methode getCause () vergleichen:

try{
  ...
} catch(Exception e){
   if(e.getCause().getClass().equals(AssertionError.class)){
      // handle your exception  1
   } else {
      // handle the rest of the world exception 
   }
} 

1

Ich hatte einen java.lang.reflect.InvocationTargetExceptionFehler von einer Anweisung, die ein Logger-Objekt in einem externen classinnerhalb eines try/ catchBlocks in meinem aufrief class.

Schreiten durch den Code in den Eclipse - Debugger und schwebt mit der Maus über die Logger Aussage , die ich den Logger sah objectwar null(einige benötigten externen Konstanten an der Spitze meines instanziiert werden class).


0

Diese Ausnahme wird ausgelöst, wenn die zugrunde liegende Methode (Methode, die mit Reflection aufgerufen wird) eine Ausnahme auslöst.

Wenn also die von der Reflection-API aufgerufene Methode eine Ausnahme auslöst (z. B. Laufzeitausnahme), wird die Exception von der Reflection-API in eine InvocationTargetException eingeschlossen.


0

Ich hatte das gleiche Problem. Ich habe e.getCause (). GetCause () verwendet und dann festgestellt, dass dies auf falsche Parameter zurückzuführen ist, die ich übergeben habe. Beim Abrufen des Werts eines der Parameter gab es eine nullPointerException. Hoffe das wird dir helfen.


-2
  1. Listen Sie alle JAR-Dateien aus dem Eclipse Navigator-Modus auf
  2. Stellen Sie sicher, dass sich alle JAR-Dateien im Binärmodus befinden

4
Wie genau überprüfen Sie, ob sich JAR-Dateien im Binärmodus befinden, indem Sie sie im Navigator anzeigen?
William

@ William du hast mich zum Lachen gebracht hahaha. Die Antwort dieses Typen sollte abgelehnt werden.
Karim Manaouil

-7

Der Fehler verschwand, nachdem ich Clean-> Run xDoclet-> Run xPackaging ausgeführt hatte.

In meinem Arbeitsbereich, in Ecllipse.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.