¿Qué podría causar java.lang.reflect.InvocationTargetException?

313

Bueno, he tratado de entender y leer lo que podría causarlo, pero no puedo entenderlo:

Tengo esto en algún lugar de mi código:

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

La cosa es que, cuando intenta invocar algún método, lanza en InvocationTargetExceptionlugar de alguna otra excepción esperada (específicamente ArrayIndexOutOfBoundsException). Como realmente sé qué método se invoca, fui directamente a este código de método y agregué un bloque try-catch para la línea que se supone que debe lanzar ArrayIndexOutOfBoundsExceptiony realmente arrojó ArrayIndexOutOfBoundsExceptioncomo se esperaba. Sin embargo, al subir, de alguna manera cambia a InvocationTargetExceptiony en el código anterior, catch(Exception e) e es InvocationTargetExceptiony no ArrayIndexOutOfBoundsException como se esperaba.

¿Qué podría causar tal comportamiento o cómo puedo verificarlo?

usuario550413
fuente

Respuestas:

333

Has agregado un nivel adicional de abstracción llamando al método con reflexión. La capa de reflexión envuelve cualquier excepción en un InvocationTargetException, lo que le permite distinguir entre una excepción realmente causada por una falla en la llamada de reflexión (tal vez su lista de argumentos no era válida, por ejemplo) y una falla dentro del método llamado.

Simplemente desenvuelva la causa dentro de InvocationTargetExceptiony obtendrá la original.

Jon Skeet
fuente
44
@ user550413: Desenvolviendo la excepción y examinándola, por supuesto. Siempre puedes tirarlo tú mismo y atraparlo de esa manera si es necesario.
Jon Skeet
157
Para cualquiera que se pregunte qué significa "desenvolver la causa dentro del InvocationTargetException", acabo de descubrir que si lo tiene impreso usando exception.printStackTrace(), simplemente mire la sección "Causado por:" en lugar de la mitad superior / sección normal.
Jan
31
Para agregar la explicación sobre "desenvolver", también puede detectar la excepción y utilizar el método getCause (), que también se puede volver a lanzar, si lo desea. Algo como try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }o...catch... { throw ex.getCause() }
jcadcell
44
+1 @HJanrs para you just look at the "Caused By:" section instead of the top half/normal section
GingerHead
1
@DheraajBhaskar No edite las respuestas de otras personas como si fueran suyas, y no utilice el formato de comillas para el texto que no se cita. Esa edición debería haberse publicado como un comentario.
Marqués de Lorne
51

La excepción se produce si

InvocationTargetException: si el método subyacente arroja una excepción.

Entonces, si el método, que se ha invocado con la API de reflexión, arroja una excepción (excepción de tiempo de ejecución, por ejemplo), la API de reflexión envolverá la excepción en un InvocationTargetException.

Andreas Dolk
fuente
gran explicación!
gaurav
¿Qué sucede si espero que el método subyacente arroje una excepción? ¿Debo tomar esta excepción y simplemente volver a lanzar?
jDub9
46

Use el getCause()método en InvocationTargetExceptionpara recuperar la excepción original.

Daniel Ward
fuente
21

Del Javadoc de Method.invoke ()

Lanza: InvocationTargetException - si el método subyacente arroja una excepción.

Esta excepción se produce si el método llamado arrojó una excepción.

Peter Lawrey
fuente
Así que imagina que tengo una cascada de java.lang.reflect.Proxyinstancias que aumentan un objeto envuelto. Cada uno Proxymaneja con gracia una excepción específica (posiblemente lanzada por el objeto envuelto) usando el suyo InvocationHandler. Para que una excepción se extienda a través de esta cascada hasta llegar al controlador / proxy de invocación correcto, en cada uno InvocationHandler, lo atraparía InvocationTargetException, desenvolvería, verificaría si la excepción envuelta es instanceofla excepción a ser manejada por esto InvocationHandler. Si no es un instanceof, lanzaría la excepción sin envolver ... ¿verdad?
Abdull
Siempre lanzaría la excepción sin envolver.
Peter Lawrey
9

Eso InvocationTargetExceptionprobablemente está terminando tu ArrayIndexOutOfBoundsException. No se puede decir por adelantado cuando se usa la reflexión lo que ese método puede arrojar, por lo que, en lugar de usar un throws Exceptionenfoque, todas las excepciones se están atrapando y envolviendo InvocationTargetException.

Liv
fuente
Gracias, pero ¿cómo diferiré entre (AssertionError e) y (Exception e) por ejemplo? Si siempre obtengo InvocationTargetException antes de desenvolver la causa, ¿en qué diferiré entre cada excepción?
user550413
9

Esto imprimirá la línea exacta de código en el método específico, que cuando se invoca, genera la excepción:

try {

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

} catch (InvocationTargetException e) {

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

    // generic exception handling
    e.printStackTrace();
}
Rocky Inde
fuente
1
Gracias; Esto me ha ayudado a darme cuenta de que mi problema no estaba en la reflexión en sí, sino dentro del método invocado.
Jose Gómez
3

Esto describe algo como,

InvocationTargetException es una excepción marcada que envuelve una excepción lanzada por un método o constructor invocado. A partir de la versión 1.4, esta excepción se ha actualizado para cumplir con el mecanismo de encadenamiento de excepciones de propósito general. La "excepción de destino" que se proporciona en el momento de la construcción y se accede a través del método getTargetException () ahora se conoce como la causa, y se puede acceder a través del método Throwable.getCause (), así como el "método heredado" mencionado anteriormente.

Sazzad Hissain Khan
fuente
2

Puede comparar con la clase de excepción original usando el método getCause () de esta manera:

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

Tuve un java.lang.reflect.InvocationTargetExceptionerror de una declaración que llama a un objeto logger en un externo classdentro de un try/ catchbloque en mi class.

Al recorrer el código en el depurador de Eclipse y al pasar el mouse sobre la instrucción del registrador, vi que el registrador objectera null(algunas constantes externas debían instanciarse en la parte superior de mi class).

Stuart Cardall
fuente
0

Esta excepción se produce si el método subyacente (método llamado usando Reflection) arroja una excepción.

Entonces, si el método, que ha sido invocado por la API de reflexión, arroja una excepción (como por ejemplo, la excepción de tiempo de ejecución), la API de reflexión envolverá la excepción en una excepción InvocationTargetException.

Nikhil Kumar
fuente
0

Estaba enfrentando el mismo problema. Usé e.getCause (). GetCause () luego descubrí que era debido a los parámetros incorrectos que estaba pasando. Hubo nullPointerException al obtener el valor de uno de los parámetros. Espero que esto te ayudará.

Deepak Vajpayee
fuente
-2
  1. Listar todos los archivos jar del modo Eclipse Navigator
  2. Verifique que todos los archivos jar estén en modo binario
Manik
fuente
44
¿Cómo verifica exactamente que los archivos jar están en modo binario al verlos en el navegador?
William
@William me hiciste reír jajaja. La respuesta de este tipo debería ser rechazada.
Karim Manaouil
-7

El error desapareció después de que hice Clean-> Run xDoclet-> Run xPackaging.

En mi espacio de trabajo, en ecllipse.

Ashutosh Singh
fuente