Qu'est-ce qui pourrait provoquer l'exception java.lang.reflect.InvocationTargetException?

313

Eh bien, j'ai essayé de comprendre et de lire ce qui pourrait en être la cause, mais je n'arrive pas à comprendre:

J'ai ceci quelque part dans mon code:

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

La chose est que, lorsqu'il essaie d'invoquer une méthode, il lève InvocationTargetExceptionau lieu d'une autre exception attendue (en particulier ArrayIndexOutOfBoundsException). Comme je sais réellement quelle méthode est invoquée, je suis allé directement à ce code de méthode et j'ai ajouté un bloc try-catch pour la ligne qui suppose de lancer ArrayIndexOutOfBoundsExceptionet il a vraiment lancé ArrayIndexOutOfBoundsExceptioncomme prévu. Pourtant, en montant, il change en quelque sorte vers InvocationTargetExceptionet dans le code ci-dessus, catch(Exception e) e n'est InvocationTargetExceptionpas ArrayIndexOutOfBoundsException comme prévu.

Qu'est-ce qui pourrait provoquer un tel comportement ou comment puis-je vérifier une telle chose?

user550413
la source

Réponses:

333

Vous avez ajouté un niveau d'abstraction supplémentaire en appelant la méthode avec réflexion. La couche de réflexion encapsule toute exception dans un InvocationTargetException, ce qui vous permet de faire la différence entre une exception réellement causée par un échec de l'appel de réflexion (peut-être que votre liste d'arguments n'était pas valide, par exemple) et un échec dans la méthode appelée.

Déballez simplement la cause dans le InvocationTargetExceptionet vous obtiendrez l'original.

Jon Skeet
la source
4
@ user550413: En dépliant l'exception et en l'examinant, bien sûr. Vous pouvez toujours le lancer vous-même et l'attraper de cette façon si vous le devez.
Jon Skeet
157
Pour ceux qui se demandent ce que signifie "déballer la cause dans le InvocationTargetException", je viens de découvrir que si vous l'avez imprimé en utilisant exception.printStackTrace(), vous regardez simplement la section "Causé par:" au lieu de la moitié supérieure / section normale.
Jan
31
Pour ajouter l'explication sur le "déballage", vous pouvez également intercepter l'exception et utiliser la méthode getCause (), qui peut également être renvoyée, si vous le souhaitez. Quelque chose comme try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }ou...catch... { throw ex.getCause() }
jcadcell
4
+1 @HJanrs pour you just look at the "Caused By:" section instead of the top half/normal section
GingerHead
1
@DheraajBhaskar Ne modifiez pas les réponses des autres comme si elles étaient les vôtres et n'utilisez pas la mise en forme des citations pour le texte qui n'est pas cité. Cette modification aurait dû être publiée en tant que commentaire.
Marquis de Lorne
51

L'exception est levée si

InvocationTargetException - si la méthode sous-jacente lève une exception.

Donc, si la méthode, qui a été invoquée avec l'API de réflexion, lève une exception (exception d'exécution par exemple), l'API de réflexion encapsulera l'exception dans un InvocationTargetException.

Andreas Dolk
la source
grande explication!
gaurav
Que faire si je m'attends à ce que la méthode sous-jacente lève une exception? Dois-je attraper cette exception et simplement recommencer?
jDub9
46

Utilisez la getCause()méthode sur le InvocationTargetExceptionpour récupérer l'exception d'origine.

Daniel Ward
la source
21

À partir du Javadoc de Method.invoke ()

Lance: InvocationTargetException - si la méthode sous-jacente lève une exception.

Cette exception est levée si la méthode appelée a levé une exception.

Peter Lawrey
la source
Imaginez donc que j'ai une cascade d' java.lang.reflect.Proxyinstances augmentant un objet enveloppé. Chacun Proxygère gracieusement une exception spécifique (éventuellement levée par l'objet encapsulé) en utilisant la sienne InvocationHandler. Pour qu'une exception se propage à travers cette cascade jusqu'à atteindre le gestionnaire / proxy d'invocation correct, dans chacun InvocationHandler, je l'attraperais InvocationTargetException, la déballerais, vérifierais si l'exception encapsulée est une instanceofexception à gérer par cela InvocationHandler. Si ce n'est pas un instanceof, je lèverais l' exception déballée ... non?
Abdull
Je lèverais toujours l'exception non emballée.
Peter Lawrey
9

C'est en InvocationTargetExceptiontrain de conclure votre ArrayIndexOutOfBoundsException. Il n'est pas possible de dire dès le départ lors de l'utilisation de la réflexion ce que cette méthode peut apporter - donc plutôt que d'utiliser une throws Exceptionapproche, toutes les exceptions sont détectées et intégrées InvocationTargetException.

Liv
la source
Merci, mais comment vais-je différer entre (AssertionError e) et (Exception e) par exemple? Si je reçois toujours InvocationTargetException avant de déballer la cause, où vais-je différer entre chaque exception?
user550413
9

Cela affichera la ligne de code exacte dans la méthode spécifique qui, lorsqu'elle est invoquée, déclenche l'exception:

try {

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

} catch (InvocationTargetException e) {

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

    // generic exception handling
    e.printStackTrace();
}
Rocky Inde
la source
1
Merci; cela m'a aidé à réaliser que mon problème n'était pas dans la réflexion elle-même, mais dans la méthode invoquée.
Jose Gómez
3

Cela décrit quelque chose comme,

InvocationTargetException est une exception vérifiée qui encapsule une exception levée par une méthode ou un constructeur invoqué. Depuis la version 1.4, cette exception a été mise à niveau pour se conformer au mécanisme de chaînage d'exceptions à usage général. L '"exception cible" qui est fournie au moment de la construction et accessible via la méthode getTargetException () est désormais connue sous le nom de cause, et peut être accessible via la méthode Throwable.getCause (), ainsi que la "méthode héritée" susmentionnée.

Sazzad Hissain Khan
la source
2

Vous pouvez comparer avec la classe d'exception d'origine en utilisant la méthode getCause () comme ceci:

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

J'ai eu une java.lang.reflect.InvocationTargetExceptionerreur provenant d'une instruction appelant un objet logger dans un externe classà l' intérieur d'un bloc try/ catchdans mon class.

En parcourant le code dans le débogueur Eclipse et en passant la souris sur l'instruction de l'enregistreur, j'ai vu que l'enregistreur objectétait null(certaines constantes externes devaient être instanciées tout en haut de mon class).

Stuart Cardall
la source
0

Cette exception est levée si la méthode sous-jacente (méthode appelée à l'aide de Reflection) lève une exception.

Ainsi, si la méthode, qui a été invoquée par l'API de réflexion, lève une exception (comme par exemple une exception d'exécution), l'API de réflexion encapsulera l'exception dans une InvocationTargetException.

Nikhil Kumar
la source
0

J'étais confronté au même problème. J'ai utilisé e.getCause (). GetCause () puis j'ai trouvé que c'était à cause de mauvais paramètres que je passais. Il y avait nullPointerException lors de la récupération de la valeur de l'un des paramètres. J'espère que ceci vous aidera.

Deepak Vajpayee
la source
-2
  1. Liste tous les fichiers jar du mode Eclipse Navigator
  2. Vérifiez que tous les fichiers jar sont en mode binaire
Manik
la source
4
Comment vérifiez-vous exactement que les fichiers jar sont en mode binaire en les affichant dans le navigateur?
William
@William tu m'as fait rire hahaha. La réponse de ce type devrait être rejetée.
Karim Manaouil
-7

L'erreur a disparu après que j'ai fait Clean-> Run xDoclet-> Run xPackaging.

Dans mon espace de travail, en éclipse.

Ashutosh Singh
la source