Что может вызвать java.lang.reflect.InvocationTargetException?

313

Ну, я пытался понять и прочитать, что может вызвать это, но я просто не могу понять:

У меня есть это где-то в моем коде:

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

Дело в том, что, когда он пытается вызвать какой-то метод, он выбрасывает InvocationTargetExceptionвместо некоторого другого ожидаемого исключения (в частности ArrayIndexOutOfBoundsException). Поскольку я на самом деле знаю, какой метод вызывается, я сразу перешел к коду этого метода и добавил блок try-catch для строки, которая предполагает выброс, ArrayIndexOutOfBoundsExceptionи он действительно выбросил, ArrayIndexOutOfBoundsExceptionкак и ожидалось. Но при переходе на это как - то меняется InvocationTargetExceptionи в приведенном выше коде catch(Exception e) е, InvocationTargetExceptionа не ArrayIndexOutOfBoundsException как ожидалось.

Что может вызвать такое поведение или как я могу проверить такую ​​вещь?

user550413
источник

Ответы:

333

Вы добавили дополнительный уровень абстракции, вызвав метод с отражением. Слой отражения оборачивает любое исключение в InvocationTargetException, что позволяет вам определить разницу между исключением, фактически вызванным ошибкой в ​​вызове отражения (например, список аргументов был недействителен) и ошибкой в ​​вызываемом методе.

Просто разверните причину внутри, InvocationTargetExceptionи вы получите исходную.

Джон Скит
источник
4
@ user550413: Развернув исключение и изучив его, конечно. Ты всегда можешь бросить это сам и поймать так, если нужно.
Джон Скит
157
Для тех, кто интересуется, что значит «развернуть причину внутри InvocationTargetException», я просто обнаружил, что если вы напечатали это, используя exception.printStackTrace(), вы просто посмотрите на раздел «Причины:» вместо раздела «верхняя половина / нормальный».
января
31
Чтобы добавить объяснение о «развёртывании», вы также можете перехватить исключение и использовать для него метод getCause (), который также может быть переброшен при желании. Что-то вроде try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }или...catch... { throw ex.getCause() }
jcadcell
4
+1 @HJanrs для you just look at the "Caused By:" section instead of the top half/normal section
GingerHead
1
@DheraajBhaskar Не редактируйте ответы других людей, как если бы они были вашими, и не используйте форматирование цитат для текста, который не цитируется. Это изменение должно быть опубликовано в качестве комментария.
Маркиз Лорн
51

Исключение выдается, если

InvocationTargetException - если базовый метод выдает исключение.

Поэтому, если метод, который был вызван с помощью API-интерфейса отражения, выдает исключение (например, исключение времени выполнения), API-интерфейс отражения преобразует исключение в InvocationTargetException.

Андреас Долк
источник
отличное объяснение!
Гаурав
Что если я ожидаю, что базовый метод сгенерирует исключение? Должен ли я поймать это исключение и просто сбросить?
jDub9
46

Используйте getCause()метод наInvocationTargetException для получения исходного исключения.

Дэниел Уорд
источник
21

Из Javadoc Method.invoke ()

Броски: InvocationTargetException - если основной метод выдает исключение.

Это исключение выдается, если вызванный метод бросил исключение.

Питер Лори
источник
Итак, представьте, что у меня есть каскад java.lang.reflect.Proxyэкземпляров, дополняющих завернутый объект. Каждый из них Proxyкорректно обрабатывает определенное исключение (возможно, выбрасываемое обернутым объектом), используя свое собственное InvocationHandler. Для исключения, которое будет распространяться через этот каскад до достижения правильного обработчика / прокси-сервера вызова, в каждом InvocationHandlerя бы поймал InvocationTargetException, развернул его, проверил, является ли instanceofисключение в оболочке исключением, которое должно обрабатываться этим InvocationHandler. Если бы это не было instanceof, я бы выбросил развернутое исключение ... верно?
Абдул
Я всегда бросал бы развернутое исключение.
Питер Лоури
9

Это InvocationTargetException, вероятно, завершение вашего ArrayIndexOutOfBoundsException. При использовании рефлексии невозможно предсказать, что может дать этот метод - поэтому вместо использования throws Exceptionподхода все исключения перехватываются и оборачиваются InvocationTargetException.

Liv
источник
Спасибо, но что, как я буду отличаться между (AssertionError e) и (Exception e), например? Если я всегда получаю InvocationTargetException, прежде чем развернуть причину, где я буду отличаться для каждого исключения?
user550413
9

Это напечатает точную строку кода в конкретном методе, который при вызове вызывает исключение:

try {

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

} catch (InvocationTargetException e) {

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

    // generic exception handling
    e.printStackTrace();
}
Роки Инд
источник
1
Спасибо; это помогло мне понять, что моя проблема была не в самом отражении, а в вызванном методе.
Хосе Гомес
3

Это описывает что-то вроде

InvocationTargetException - это проверенное исключение, которое переносит исключение, выброшенное вызванным методом или конструктором. Начиная с версии 1.4 это исключение было модифицировано для соответствия механизму цепочки исключений общего назначения. «Целевое исключение», которое предоставляется во время построения и доступно через метод getTargetException (), теперь известно как причина, и к нему можно получить доступ через метод Throwable.getCause (), а также вышеупомянутый «устаревший метод».

Саззад Хисейн Хан
источник
2

Вы можете сравнить с исходным классом исключений, используя метод getCause () следующим образом:

try{
  ...
} catch(Exception e){
   if(e.getCause().getClass().equals(AssertionError.class)){
      // handle your exception  1
   } else {
      // handle the rest of the world exception 
   }
} 
Мехди
источник
1

У меня была java.lang.reflect.InvocationTargetExceptionошибка из заявления вызывающего объекта регистратор во внешнем classвнутри try/ catchблока по моему class.

Пройдя по коду в отладчике Eclipse и наведя указатель мыши на оператор logger, я увидел, что logger objectбыл null(некоторые внешние константы должны быть созданы в самом верху моего class).

Стюарт Кардалл
источник
0

Это исключение выдается, если базовый метод (метод, вызванный с помощью Reflection) выдает исключение.

Поэтому, если метод, который был вызван API-интерфейсом отражения, выдает исключение (как, например, исключение времени выполнения), API-интерфейс отражения преобразует исключение в InvocationTargetException.

Нихил Кумар
источник
0

Я столкнулся с той же проблемой. Я использовал e.getCause (). GetCause (), затем обнаружил, что это из-за неверных параметров, которые я передавал. При извлечении значения одного из параметров было исключение nullPointerException. Надеюсь, что это поможет вам.

Дипак Ваджпаи
источник
-2
  1. Вывести список всех jar-файлов из режима Eclipse Navigator
  2. Убедитесь, что все файлы JAR находятся в двоичном режиме
Маник
источник
4
Как именно вы проверяете файлы JAR в двоичном режиме, просматривая их в навигаторе?
Уильям
@ Уильям, ты меня рассмешил, хахаха. Ответ этого парня должен быть опущен.
Карим Манауй
-7

Ошибка исчезла после того, как я сделал Clean-> Run xDoclet-> Run xPackaging.

В моем рабочем пространстве, в затмении.

Ашутош Сингх
источник