Cosa potrebbe causare java.lang.reflect.InvocationTargetException?


313

Bene, ho cercato di capire e leggere cosa potrebbe causarlo, ma non riesco proprio a capirlo:

Ho questo da qualche parte nel mio codice:

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

Il fatto è che, quando tenta di invocare un metodo, genera InvocationTargetExceptioninvece un'altra eccezione prevista (in particolare ArrayIndexOutOfBoundsException). Dato che in realtà so quale metodo viene invocato, sono andato direttamente a questo codice di metodo e ho aggiunto un blocco try-catch per la linea che si suppone di lanciare ArrayIndexOutOfBoundsExceptione che è stato effettivamente lanciato ArrayIndexOutOfBoundsExceptioncome previsto. Tuttavia, quando si sale, in qualche modo cambia InvocationTargetExceptione nel codice sopra catch(Exception e) e è InvocationTargetExceptione non ArrayIndexOutOfBoundsException come previsto.

Cosa potrebbe causare un simile comportamento o come posso verificare una cosa del genere?

Risposte:


333

Hai aggiunto un ulteriore livello di astrazione chiamando il metodo con la riflessione. Il layer di riflessione racchiude qualsiasi eccezione in un InvocationTargetException, che consente di distinguere tra un'eccezione effettivamente causata da un errore nella chiamata di riflessione (forse l'elenco degli argomenti non era valido, ad esempio) e un errore all'interno del metodo chiamato.

Basta scartare la causa all'interno InvocationTargetExceptione arriverai a quella originale.


4
@ user550413: scartando l'eccezione ed esaminandola, ovviamente. Puoi sempre lanciarlo da solo e prenderlo in quel modo, se necessario.
Jon Skeet,

157
Per chiunque si chiedesse cosa significhi "scartare la causa all'interno del InvocationTargetException", ho appena scoperto che se lo hai stampato usando exception.printStackTrace(), basta guardare la sezione "Causato da:" invece della metà superiore / sezione normale.
gennaio

31
Per aggiungere la spiegazione su "unwrapping" puoi anche prendere l'eccezione e usare il metodo getCause (), che può anche essere riprogrammato, se lo desideri. Qualcosa del genere try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }o...catch... { throw ex.getCause() }
jcadcell,

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

1
@DheraajBhaskar Non modificare le risposte degli altri come se fossero le tue e non usare la formattazione delle virgolette per il testo che non è citato. Quella modifica avrebbe dovuto essere pubblicata come commento.
Marchese di Lorne,

51

L'eccezione viene generata se

InvocationTargetException - se il metodo sottostante genera un'eccezione.

Quindi, se il metodo, che è stato invocato con l'API di reflection, genera un'eccezione (ad esempio un'eccezione di runtime), l'API di riflessione inserirà l'eccezione in un InvocationTargetException.


ottima spiegazione!
gaurav,

Cosa succede se mi aspetto che il metodo sottostante generi un'eccezione? Dovrei cogliere questa eccezione e semplicemente ricominciare?
jDub9,

46

Utilizzare il getCause()metodo su InvocationTargetExceptionper recuperare l'eccezione originale.


21

Dal Javadoc di Method.invoke ()

Produce: InvocationTargetException - se il metodo sottostante genera un'eccezione.

Questa eccezione viene generata se il metodo chiamato ha generato un'eccezione.


Quindi immagina di avere una cascata di java.lang.reflect.Proxyistanze che aumentano un oggetto avvolto. Ognuno Proxygestisce con garbo un'eccezione specifica (eventualmente generata dall'oggetto avvolto) usando la propria InvocationHandler. Affinché un'eccezione si propaghi attraverso questa cascata fino a raggiungere il gestore / proxy di invocazione corretto, in ciascuno InvocationHandler, lo prenderei InvocationTargetException, lo scarterei, controllerei se l'eccezione racchiusa è instanceofun'eccezione che deve essere gestita da questo InvocationHandler. Se non fosse un instanceof, darei l' eccezione da scartare ... giusto?
Abdull,

Darei sempre l'eccezione da scartare.
Peter Lawrey,

9

Questo InvocationTargetExceptionprobabilmente sta concludendo il tuo ArrayIndexOutOfBoundsException. Quando si usa la riflessione non si può dire in anticipo cosa può lanciare quel metodo - quindi piuttosto che usare un throws Exceptionapproccio, tutte le eccezioni vengono catturate e racchiuse InvocationTargetException.


Grazie, ma che differenza farò tra (AssertionError e) e (Exception e) per esempio? Se ricevo sempre InvocationTargetException prima di scartare la causa, dove differirò tra ciascuna eccezione?
user550413,

9

Questo stamperà la riga esatta di codice nel metodo specifico che, quando richiamato, ha sollevato l'eccezione:

try {

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

} catch (InvocationTargetException e) {

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

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

1
Grazie; questo mi ha aiutato a capire che il mio problema non era nella riflessione stessa, ma nel metodo invocato.
Jose Gómez,

3

Questo descrive qualcosa come

InvocationTargetException è un'eccezione controllata che racchiude un'eccezione generata da un metodo o un costruttore richiamato. A partire dalla versione 1.4, questa eccezione è stata adattata per adeguarsi al meccanismo di concatenamento delle eccezioni per scopi generali. L '"eccezione di destinazione" che viene fornita in fase di costruzione e alla quale si accede tramite il metodo getTargetException () è ora nota come causa e si può accedere tramite il metodo Throwable.getCause (), nonché con il suddetto "metodo legacy".


2

Puoi confrontare con l'eccezione originale Class usando il metodo getCause () in questo modo:

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

1

Ho avuto un java.lang.reflect.InvocationTargetExceptionerrore da una dichiarazione che chiede un oggetto logger in un esterno classall'interno di un try/ catchblocco nel mio class.

Scorrendo il codice nel debugger di Eclipse e passando il mouse sull'istruzione logger ho visto che il logger objectera null(alcune costanti esterne dovevano essere istanziate nella parte superiore della mia class).


0

Questa eccezione viene generata se il metodo sottostante (metodo chiamato utilizzando Reflection) genera un'eccezione.

Pertanto, se il metodo, che è stato invocato dall'API di reflection, genera un'eccezione (come ad esempio un'eccezione di runtime), l'API di riflessione avvolge l'eccezione in InvocationTargetException.


0

Stavo affrontando lo stesso problema. Ho usato e.getCause (). GetCause () poi ho scoperto che era a causa di parametri sbagliati che stavo passando. C'è stato nullPointerException nel recupero del valore di uno dei parametri. Spero che questo ti possa aiutare.


-2
  1. Elenca tutti i file jar dalla modalità Eclipse Navigator
  2. Verificare che tutti i file jar siano in modalità binaria

4
Come si verifica esattamente che i file jar siano in modalità binaria visualizzandoli nel Navigator?
William,

@William mi hai fatto ridere hahaha. La risposta di questo ragazzo dovrebbe essere sottovalutata.
Karim Manaouil,

-7

L'errore è scomparso dopo aver eseguito Clean-> Esegui xDoclet-> Esegui xPackaging.

Nel mio spazio di lavoro, in ecllipse.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.