Що може спричинити java.lang.reflect.InvocationTargetException?


313

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

У мене це є десь у коді:

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

Річ у тому, що, коли він намагається викликати якийсь метод, він викидає InvocationTargetExceptionзамість якогось іншого очікуваного винятку (конкретно ArrayIndexOutOfBoundsException). Оскільки я насправді знаю, який метод викликається, я перейшов до цього коду методу і додав блок пробного входу для рядка, який передбачається кинути, ArrayIndexOutOfBoundsExceptionі він справді кинув, ArrayIndexOutOfBoundsExceptionяк очікувалося. Однак при підйомі вгору якимось чином змінюється на InvocationTargetExceptionі в коді вище catch(Exception e) e є, InvocationTargetExceptionа не так, ArrayIndexOutOfBoundsException як очікувалося.

Що може спричинити таку поведінку чи як я можу перевірити таке?

Відповіді:


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 for you just look at the "Caused By:" section instead of the top half/normal section
GingerHead

1
@DheraajBhaskar Не редагуйте відповіді інших людей так, ніби вони були вашими, і не використовуйте форматування цитат для тексту, який не цитується. Цю редакцію слід було розмістити як коментар.
Маркіз Лорн

51

Виняток кидається, якщо

InvocationTargetException - якщо базовий метод кидає виняток.

Отже, якщо метод, на який було викликано API відбиття, викидає виняток (наприклад, виняток із виконання), API відображення перетворить виняток у InvocationTargetException.


чудове пояснення!
gaurav

Що робити, якщо я очікую, що основний метод видасть виняток? Чи варто спіймати цей виняток і просто перекинутись?
jDub9


21

Від Javadoc з Method.invoke ()

Throw: InvocationTargetException - якщо базовий метод кидає виняток.

Цей виняток кидається, якщо метод, який називається, кинув виняток.


Тож уявіть, що у мене є каскад java.lang.reflect.Proxyекземплярів, що збільшують обгорнутий об’єкт. Кожен Proxyвитончено обробляє конкретний виняток (можливо, кинутий загорнутим предметом), використовуючи свій власний InvocationHandler. Для виключення, щоб прошивати цей каскад до досягнення правильного обробника виклику / проксі-сервера, у кожному InvocationHandlerя би впіймав InvocationTargetException, розгорнув його, перевірив, чи завершений виняток є instanceofвинятком, який слід обробляти цим InvocationHandler. Якщо це не так instanceof, я б кинув розгорнуте виняток ... правда?
Абдулл

Я б завжди кидав розгорнуте виняток.
Пітер Лорі

9

Це InvocationTargetException, ймовірно, завершує ваше ArrayIndexOutOfBoundsException. При використанні роздумів немає заздалегідь розмови про те, що цей метод може кинути, тож замість того, щоб використовувати throws Exceptionпідхід, всі винятки опиняються та переховуються InvocationTargetException.


Дякую, але що я буду відрізняти (AssertionError e) та (Exception e), наприклад? Якщо я завжди отримую InvocationTargetException першим, перш ніж розгортати причину, де я буду відрізнятись між кожним винятком?
користувач550413

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 та наведення миші на виписку журналу, я побачив, що в ньому objectбув реєстратор null(деякі зовнішні константи потрібно було екземплярувати в самому верху мого class).


0

Цей виняток кидається, якщо базовий метод (метод, який називається Reflection) кидає виняток.

Отже, якщо метод, на який викликається API відображення, видає виняток (як, наприклад, виняток під час виконання), API відображення перетворить виняток у InvocationTargetException.


0

Я зіткнувся з тією ж проблемою. Я використовував e.getCause (). GetCause (), тоді я виявив, що це було через неправильні параметри, які я проходив. Існує nullPointerException при отриманні значення одного з параметрів. Сподіваюся, що це вам допоможе.


-2
  1. Список усіх файлів jar із режиму навігатора Eclipse
  2. Перевірте, чи всі файли jar перебувають у двійковому режимі

4
Як саме ви підтверджуєте, що файли jar перебувають у двійковому режимі, переглядаючи їх у Навігаторі?
Вільям

@William ти змусив мене сміятися ха-ха. Відповідь цього хлопця слід оскаржувати.
Карім Манауїл

-7

Помилка зникла після того, як я зробив Clean-> Run xDoclet-> Run xPackaging.

У моєму робочому просторі, в затемненні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.