O que poderia causar o java.lang.reflect.InvocationTargetException?

313

Bem, tentei entender e ler o que poderia causar isso, mas simplesmente não consigo:

Eu tenho isso em algum lugar no meu código:

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

O problema é que, quando tenta invocar algum método, lança em InvocationTargetExceptionvez de outra exceção esperada (especificamente ArrayIndexOutOfBoundsException). Como eu realmente sei qual método é chamado, fui direto para esse código de método e adicionei um bloco try-catch para a linha que deveria ser lançada ArrayIndexOutOfBoundsExceptione realmente foi lançada ArrayIndexOutOfBoundsExceptionconforme o esperado. No entanto, ao subir, de alguma forma, muda para InvocationTargetExceptione no código acima catch(Exception e) e é InvocationTargetExceptione não ArrayIndexOutOfBoundsException o esperado.

O que poderia causar esse comportamento ou como posso verificar isso?

user550413
fonte

Respostas:

333

Você adicionou um nível extra de abstração chamando o método com reflexão. A camada de reflexão envolve qualquer exceção em um InvocationTargetException, o que permite dizer a diferença entre uma exceção realmente causada por uma falha na chamada de reflexão (talvez sua lista de argumentos não seja válida, por exemplo) e uma falha no método chamado.

Apenas desembrulhe a causa InvocationTargetExceptione você chegará à original.

Jon Skeet
fonte
4
@ user550413: Desembrulhando a exceção e examinando-a, é claro. Você sempre pode jogá-lo sozinho e pegá-lo dessa maneira, se for necessário.
Jon Skeet
157
Para quem quer saber o que significa "desembrulhar a causa dentro do InvocationTargetException", descobri que, se você a imprimiu usando exception.printStackTrace(), basta olhar para a seção "Causada por:" em vez da metade superior / normal.
Janeiro
31
Para adicionar a explicação sobre "desembrulhar", você também pode capturar a exceção e usar o método getCause (), que também pode ser mostrado novamente, se desejado. Algo como try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }ou...catch... { throw ex.getCause() }
jcadcell 13/09/12
4
1 @HJanrs for you just look at the "Caused By:" section instead of the top half/normal section
GingerHead 12/12/12
1
@DheraajBhaskar Não edite as respostas de outras pessoas como se fossem suas e não use formatação de citação para texto que não está entre aspas. Essa edição deveria ter sido postada como um comentário.
Marquês de Lorne
51

A exceção é lançada se

InvocationTargetException - se o método subjacente lança uma exceção.

Portanto, se o método, que foi chamado pela API de reflexão, lançar uma exceção (exceção de tempo de execução, por exemplo), a API de reflexão envolverá a exceção em um InvocationTargetException.

Andreas Dolk
fonte
ótima explicação!
31819
E se eu esperar que o método subjacente gere uma exceção? Devo pegar essa exceção e simplesmente repetir novamente?
JDub9
46

Use o getCause()método no InvocationTargetExceptionpara recuperar a exceção original.

Daniel Ward
fonte
21

No Javadoc do Method.invoke ()

Lança: InvocationTargetException - se o método subjacente lança uma exceção.

Essa exceção é lançada se o método chamado lançou uma exceção.

Peter Lawrey
fonte
Imagine que eu tenho uma cascata de java.lang.reflect.Proxyinstâncias aumentando um objeto empacotado. Cada Proxyum manipula graciosamente uma exceção específica (possivelmente lançada pelo objeto quebrado) usando sua própria InvocationHandler. Para que uma exceção percorra essa cascata até atingir o manipulador / proxy de chamada correto, em cada uma delas InvocationHandlereu capturaria InvocationTargetException, desembrulharia e verificaria se a exceção agrupada é instanceofa exceção a ser tratada por isso InvocationHandler. Se não for um instanceof, eu lançaria a exceção desembrulhada ... certo?
Abdull
Eu sempre lançaria a exceção desembrulhada.
precisa saber é o seguinte
9

Isso InvocationTargetExceptionprovavelmente está encerrando o seu ArrayIndexOutOfBoundsException. Não há como dizer antecipadamente ao usar a reflexão o que esse método pode oferecer - portanto, em vez de usar uma throws Exceptionabordagem, todas as exceções estão sendo capturadas e agrupadas InvocationTargetException.

Liv
fonte
Obrigado, mas como vou diferir entre (AssertionError e) e (Exception e) por exemplo? Se eu sempre obtiver InvocationTargetException antes de desembrulhar a causa, onde diferirei entre cada exceção?
User550413
9

Isso imprimirá a linha exata de código no método específico que, quando chamado, gerou a exceção:

try {

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

} catch (InvocationTargetException e) {

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

    // generic exception handling
    e.printStackTrace();
}
Rocky Inde
fonte
1
Obrigado; isso me ajudou a perceber que meu problema não estava na reflexão em si, mas no método invocado.
Jose Gómez
3

Isso descreve algo como,

InvocationTargetException é uma exceção verificada que envolve uma exceção lançada por um método ou construtor chamado. A partir do release 1.4, essa exceção foi adaptada para estar em conformidade com o mecanismo de encadeamento de exceções de uso geral. A "exceção de destino" fornecida no momento da construção e acessada pelo método getTargetException () agora é conhecida como causa, e pode ser acessada pelo método Throwable.getCause (), bem como pelo método "legado" mencionado acima.

Sazzad Hissain Khan
fonte
2

Você pode comparar com a exceção original Class usando o método getCause () como este:

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

Eu tive um java.lang.reflect.InvocationTargetExceptionerro de uma instrução chamando um objeto logger em um externo classdentro de um bloco try/ catchno meu class.

Percorrendo o código no depurador Eclipse & passar o mouse sobre a declaração logger vi o logger objectfoi null(algumas constantes externos necessários para ser instanciado no topo da minha class).

Stuart Cardall
fonte
0

Essa exceção é lançada se o método subjacente (método chamado usando Reflexão) lança uma exceção.

Portanto, se o método, que foi chamado pela API de reflexão, lançar uma exceção (como por exemplo, exceção de tempo de execução), a API de reflexão envolverá a exceção em um InvocationTargetException.

Nikhil Kumar
fonte
0

Eu estava enfrentando o mesmo problema. Eu usei e.getCause (). GetCause () e descobri que era por causa de parâmetros errados que eu estava passando. Houve nullPointerException na busca do valor de um dos parâmetros. Espero que isso ajude você.

Deepak Vajpayee
fonte
-2
  1. Listar todos os arquivos jar no modo Navegador Eclipse
  2. Verifique se todos os arquivos jar estão no modo binário
Manik
fonte
4
Como exatamente você verifica se os arquivos jar estão no modo binário, visualizando-os no Navegador?
William
@ William você me fez rir hahaha. A resposta desse cara deve ser votada abaixo.
Karim Manaouil
-7

O erro desapareceu depois que eu fiz Limpar-> Executar xDoclet-> Executar xPackaging.

No meu espaço de trabalho, em eclipse.

Ashutosh Singh
fonte