Co może powodować wyjątek java.lang.reflect.InvocationTargetException?

313

Próbowałem zrozumieć i przeczytać, co może to spowodować, ale po prostu nie mogę tego zrozumieć:

Mam to gdzieś w moim kodzie:

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

Chodzi o to, że gdy próbuje wywołać jakąś metodę, rzuca InvocationTargetExceptionzamiast jakiegoś innego oczekiwanego wyjątku (konkretnie ArrayIndexOutOfBoundsException). Ponieważ tak naprawdę wiem, która metoda jest wywoływana, przeszedłem prosto do tego kodu metody i dodałem blok try-catch dla linii, która ma się rzucać ArrayIndexOutOfBoundsExceptioni naprawdę rzuciła ArrayIndexOutOfBoundsExceptionzgodnie z oczekiwaniami. Jednak gdy idziemy w górę, jakoś zmienia się InvocationTargetExceptionw powyższym kodzie iw kodzie catch(Exception e) e jest InvocationTargetExceptioni nie jest ArrayIndexOutOfBoundsException zgodnie z oczekiwaniami.

Co może powodować takie zachowanie lub jak mogę sprawdzić takie rzeczy?

użytkownik550413
źródło

Odpowiedzi:

333

Dodałeś dodatkowy poziom abstrakcji, wywołując metodę z odbiciem. Warstwa odbijająca otacza każdy wyjątek w InvocationTargetException, co pozwala odróżnić wyjątek faktycznie spowodowany niepowodzeniem wywołania odbicia (może na przykład lista argumentów nie była poprawna) i niepowodzeniem w wywoływanej metodzie.

Po prostu rozpakuj przyczynę wewnątrz, InvocationTargetExceptiona dojdziesz do pierwotnej.

Jon Skeet
źródło
4
@ user550413: Oczywiście, rozpakowując wyjątek i sprawdzając go. Zawsze możesz rzucić go sam i złapać w ten sposób, jeśli musisz.
Jon Skeet
157
Dla każdego, kto zastanawia się, co to znaczy „rozpakować przyczynę w obrębie InvocationTargetException”, właśnie odkryłem, że jeśli masz to wydrukowane za pomocą exception.printStackTrace(), po prostu spójrz na sekcję „Przyczyna:” zamiast górnej połowy / normalnej sekcji.
stycznia
31
Aby dodać wyjaśnienie dotyczące „rozpakowywania”, możesz również złapać wyjątek i użyć na nim metody getCause (), którą w razie potrzeby można również ponownie włączyć. Coś w stylu try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }lub...catch... { throw ex.getCause() }
jcadcell,
4
+1 @HJanrs za you just look at the "Caused By:" section instead of the top half/normal section
GingerHead 12.12.12
1
@DheraajBhaskar Nie edytuj odpowiedzi innych osób tak, jakby były twoje, i nie używaj formatowania cytatów dla tekstu, który nie jest cytowany. Ta edycja powinna była zostać opublikowana jako komentarz.
Markiz Lorne
51

Wyjątek jest zgłaszany, jeśli

InvocationTargetException - jeśli metoda bazowa zgłasza wyjątek.

Jeśli więc metoda, która została wywołana za pomocą interfejsu API refleksji, zgłosi wyjątek (na przykład wyjątek środowiska wykonawczego), interfejs API refleksji zapisze wyjątek w zmiennej InvocationTargetException.

Andreas Dolk
źródło
świetne wyjaśnienie!
gaurav
Co się stanie, jeśli spodziewam się, że metoda podstawowa zgłosi wyjątek? Czy powinienem złapać ten wyjątek i po prostu ponownie rzucić?
jDub9
46

Użyj getCause()metody na, InvocationTargetExceptionaby pobrać oryginalny wyjątek.

Daniel Ward
źródło
21

Z Javadoc metody Method.invoke ()

Zgłasza: InvocationTargetException - jeśli metoda bazowa zgłasza wyjątek.

Ten wyjątek jest zgłaszany, jeśli wywołana metoda zgłosiła wyjątek.

Peter Lawrey
źródło
Wyobraź sobie, że mam kaskadę java.lang.reflect.Proxyprzypadków powiększania owiniętego obiektu. Każdy z Proxywdziękiem obsługuje określony wyjątek (być może zgłoszony przez zawinięty obiekt), używając własnego InvocationHandler. Aby wyjątek przeszedł przez tę kaskadę aż do osiągnięcia właściwego modułu obsługi / proxy wywołania, w każdym z nich InvocationHandlerwychwyciłem InvocationTargetException, rozpakowałem go, sprawdziłem, czy zawinięty wyjątek jest instanceofwyjątkiem, który ma zostać obsłużony InvocationHandler. Jeśli nie instanceof, rzuciłbym nieopakowany wyjątek ... prawda?
Abdull,
Zawsze rzucałbym nieopakowany wyjątek.
Peter Lawrey,
9

To InvocationTargetExceptionprawdopodobnie kończy twoje ArrayIndexOutOfBoundsException. Używając refleksji, nie da się powiedzieć z góry, co ta metoda może rzucić - więc zamiast stosować throws Exceptionpodejście, wszystkie wyjątki są wychwytywane i zamykane InvocationTargetException.

Liv
źródło
Dzięki, ale w jaki sposób będę się różnić między (AssertionError e) i (Exception e) na przykład? Jeśli zawsze otrzymam InvocationTargetException przed rozpakowaniem przyczyny, gdzie będę się różnić między poszczególnymi wyjątkami?
user550413
9

Spowoduje to wydrukowanie dokładnego wiersza kodu w określonej metodzie, która po wywołaniu zgłosiła wyjątek:

try {

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

} catch (InvocationTargetException e) {

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

    // generic exception handling
    e.printStackTrace();
}
Rocky Inde
źródło
1
Dzięki; pomogło mi to uświadomić sobie, że mój problem nie dotyczył samej refleksji, ale metody, która została przywołana.
Jose Gómez
3

To opisuje coś takiego,

InvocationTargetException to sprawdzony wyjątek, który otacza wyjątek zgłoszony przez wywoływaną metodę lub konstruktor. Od wersji 1.4 wyjątek ten został zmodernizowany, aby był zgodny z mechanizmem łączenia wyjątków ogólnego przeznaczenia. „Wyjątek docelowy”, który jest udostępniany w czasie budowy i dostępny za pośrednictwem metody getTargetException (), jest teraz znany jako przyczyna i można uzyskać do niego dostęp za pomocą metody Throwable.getCause (), a także wspomnianej wcześniej „metody starszej”.

Sazzad Hissain Khan
źródło
2

Możesz porównać z oryginalną klasą wyjątków za pomocą metody getCause () w następujący sposób:

try{
  ...
} catch(Exception e){
   if(e.getCause().getClass().equals(AssertionError.class)){
      // handle your exception  1
   } else {
      // handle the rest of the world exception 
   }
} 
Mehdi
źródło
1

Wystąpił java.lang.reflect.InvocationTargetExceptionbłąd w instrukcji wywołującej obiekt rejestrujący w zewnętrznym bloku / w moim classpliku .trycatchclass

Przechodząc przez kod w debuggerze Eclipse i najeżdżając myszką na instrukcję loggera, zauważyłem, że logger objectbył null(niektóre stałe zewnętrzne musiały być tworzone na samym szczycie mojej class).

Stuart Cardall
źródło
0

Ten wyjątek jest zgłaszany, jeśli podstawowa metoda (metoda nazywana za pomocą Reflection) zgłasza wyjątek.

Jeśli więc metoda, która została wywołana przez API refleksji, zgłasza wyjątek (jak na przykład wyjątek środowiska wykonawczego), API refleksji zawinie wyjątek w InvocationTargetException.

Nikhil Kumar
źródło
0

Miałem ten sam problem. Użyłem e.getCause (). GetCause (), a potem okazało się, że to z powodu niepoprawnych parametrów, które przekazałem. Podczas pobierania wartości jednego z parametrów wystąpił wyjątek nullPointerException. Mam nadzieję, że to ci pomoże.

Deepak Vajpayee
źródło
-2
  1. Wyświetl listę wszystkich plików jar z trybu Eclipse Navigator
  2. Sprawdź, czy wszystkie pliki jar są w trybie binarnym
Manik
źródło
4
Jak dokładnie weryfikujesz pliki jar w trybie binarnym, przeglądając je w Nawigatorze?
William
@William rozśmieszyłeś mnie hahaha. Odpowiedź tego faceta powinna zostać zanegowana.
Karim Manaouil
-7

Błąd zniknął po tym, jak zrobiłem Clean-> Run xDoclet-> Run xPackaging.

W moim obszarze roboczym, w ecllipse.

Ashutosh Singh
źródło