Điều gì có thể gây ra java.lang.reflect.InvocationTargetException?


313

Chà, tôi đã cố gắng hiểu và đọc những gì có thể gây ra nhưng tôi không thể hiểu được:

Tôi có cái này ở đâu đó trong mã của tôi:

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

Điều đó là, khi nó cố gắng gọi một số phương thức, nó sẽ ném InvocationTargetExceptionthay vì một số ngoại lệ dự kiến ​​khác (cụ thể ArrayIndexOutOfBoundsException). Vì tôi thực sự biết phương thức nào được gọi, tôi đã đi thẳng vào mã phương thức này và thêm một khối thử bắt cho dòng giả sử ném ArrayIndexOutOfBoundsExceptionvà nó thực sự đã ném ArrayIndexOutOfBoundsExceptionnhư mong đợi. Tuy nhiên, khi đi lên nó bằng cách nào đó thay đổi để InvocationTargetExceptionvà trong đoạn code trên catch(Exception e) e là InvocationTargetExceptionvà không ArrayIndexOutOfBoundsException như mong đợi.

Điều gì có thể gây ra một hành vi như vậy hoặc làm thế nào tôi có thể kiểm tra một điều như vậy?

Câu trả lời:


333

Bạn đã thêm một mức độ trừu tượng bằng cách gọi phương thức với sự phản chiếu. Lớp phản chiếu bao bọc bất kỳ ngoại lệ nào trong một InvocationTargetException, cho phép bạn phân biệt sự khác biệt giữa một ngoại lệ thực sự gây ra bởi lỗi trong cuộc gọi phản chiếu (ví dụ, có thể danh sách đối số của bạn không hợp lệ) và lỗi trong phương thức được gọi.

Chỉ cần giải quyết nguyên nhân trong InvocationTargetExceptionvà bạn sẽ đi đến nguyên nhân ban đầu.


4
@ user550413: Bằng cách hủy bỏ ngoại lệ và kiểm tra điều đó, tất nhiên. Bạn luôn có thể tự ném nó, và bắt nó theo cách đó nếu bạn phải.
Jon Skeet

157
Đối với bất kỳ ai thắc mắc về ý nghĩa của việc "giải quyết nguyên nhân bên trong InvocationTargetException", tôi chỉ phát hiện ra rằng nếu bạn đã in nó bằng cách sử dụng exception.printStackTrace(), bạn chỉ cần xem phần "Nguyên nhân:" thay vì nửa trên / phần thông thường.
Jan

31
Để thêm phần giải thích về "hủy ghép", bạn cũng có thể bắt ngoại lệ và sử dụng phương thức getCause () trên đó, cũng có thể được rút lại, nếu muốn. Một cái gì đó như try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }hoặc...catch... { throw ex.getCause() }
jcadcell

4
+1 @HJanrs cho you just look at the "Caused By:" section instead of the top half/normal section
GingerHead

1
@DheraajBhaskar Đừng chỉnh sửa câu trả lời của người khác như thể họ là của riêng bạn và không sử dụng định dạng trích dẫn cho văn bản không được trích dẫn. Chỉnh sửa đó nên được đăng dưới dạng một bình luận.
Hầu tước Lorne

51

Ngoại lệ được ném nếu

InvocationTargetException - nếu phương thức cơ bản ném ngoại lệ.

Vì vậy, nếu phương thức, được gọi bằng API phản chiếu, sẽ ném một ngoại lệ (ví dụ ngoại lệ thời gian chạy), API phản chiếu sẽ bao bọc ngoại lệ thành một InvocationTargetException.


giải thích tuyệt vời!
gaurav

Điều gì xảy ra nếu tôi mong đợi phương thức cơ bản sẽ ném ngoại lệ? Tôi có nên bắt ngoại lệ này và chỉ cần nghĩ lại?
jDub9

46

Sử dụng getCause()phương pháp trên InvocationTargetExceptionđể lấy ngoại lệ ban đầu.


21

Từ Javadoc của Phương thức.invoke ()

Ném: InvocationTargetException - nếu phương thức cơ bản ném ngoại lệ.

Ngoại lệ này được ném nếu phương thức được gọi là ngoại lệ.


Vì vậy, hãy tưởng tượng tôi có một loạt các java.lang.reflect.Proxytrường hợp gia tăng một đối tượng được bọc. Mỗi cái Proxyduyên dáng xử lý một ngoại lệ cụ thể (có thể được ném bởi đối tượng được bọc) bằng cách sử dụng riêng của nó InvocationHandler. Đối với một ngoại lệ để gợn qua tầng này cho đến khi đạt được trình xử lý / proxy gọi chính xác, trong mỗi InvocationHandler, tôi sẽ nắm bắt InvocationTargetException, gỡ bỏ nó, kiểm tra xem ngoại lệ được bao bọc có phải là instanceofngoại lệ được xử lý bởi điều này không InvocationHandler. Nếu nó không phải là một instanceof, tôi sẽ ném ngoại lệ không được bao bọc ... phải không?
Abdull

Tôi sẽ luôn luôn ném ngoại lệ không được bao bọc.
Peter Lawrey

9

Đó InvocationTargetExceptioncó lẽ là gói của bạn ArrayIndexOutOfBoundsException. Không có gì để nói trước khi sử dụng sự phản chiếu những gì phương pháp đó có thể ném - vì vậy thay vì sử dụng một throws Exceptioncách tiếp cận, tất cả các ngoại lệ đang bị bắt và gói gọn trong đó InvocationTargetException.


Cảm ơn, nhưng tôi sẽ khác nhau như thế nào giữa (AssertsError e) và (Exception e) chẳng hạn? Nếu tôi luôn nhận được InvocationTargetException trước khi hủy bỏ nguyên nhân thì tôi sẽ khác nhau giữa mỗi ngoại lệ ở đâu?
dùng550413

9

Điều này sẽ in dòng mã chính xác trong phương thức cụ thể, khi được gọi, đã đưa ra ngoại lệ:

try {

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

} catch (InvocationTargetException e) {

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

    // generic exception handling
    e.printStackTrace();
}

1
Cảm ơn; điều này đã giúp tôi nhận ra rằng vấn đề của tôi không nằm ở chính sự phản chiếu, mà nằm trong phương thức được viện dẫn.
Jose Gómez

3

Điều này mô tả một cái gì đó như,

InvocationTargetException là một ngoại lệ được kiểm tra bao bọc một ngoại lệ được ném bởi một phương thức hoặc hàm tạo được gọi. Kể từ phiên bản 1.4, ngoại lệ này đã được trang bị thêm để phù hợp với cơ chế xâu chuỗi ngoại lệ cho mục đích chung. "Ngoại lệ đích" được cung cấp tại thời điểm xây dựng và được truy cập thông qua phương thức getTargetException () hiện được gọi là nguyên nhân và có thể được truy cập thông qua phương thức throwable.getCause (), cũng như phương thức "kế thừa" đã nói ở trên.


2

Bạn có thể so sánh với Lớp ngoại lệ ban đầu bằng phương thức getCause () như thế này:

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

1

Tôi đã có một java.lang.reflect.InvocationTargetExceptionlỗi từ một câu lệnh gọi một đối tượng logger ở bên ngoài classbên trong một khối try/ catchtrong của tôi class.

Bước qua mã trong trình gỡ lỗi Eclipse và di chuột qua câu lệnh logger tôi thấy logger objectnull(một số hằng số bên ngoài cần phải được khởi tạo ở đầu của tôi class).


0

Ngoại lệ này được ném nếu phương thức cơ bản (phương thức được gọi là sử dụng Reflection) ném ngoại lệ.

Vì vậy, nếu phương thức, được gọi bởi API phản chiếu, sẽ ném ra một ngoại lệ (ví dụ như ngoại lệ thời gian chạy), API phản chiếu sẽ bao bọc ngoại lệ thành InvocationTargetException.


0

Tôi đã phải đối mặt với cùng một vấn đề. Tôi đã sử dụng e.getCause (). GetCause () sau đó tôi thấy rằng đó là do tham số sai mà tôi đã truyền. Có nullPulumException trong việc tìm nạp giá trị của một trong các tham số. Hy vọng điều này sẽ giúp bạn.


-2
  1. Liệt kê tất cả các tệp jar từ chế độ Điều hướng Eclipse
  2. Xác minh rằng tất cả các tệp jar ở chế độ nhị phân

4
Làm thế nào chính xác để bạn xác minh các tệp jar ở chế độ nhị phân bằng cách xem chúng trong Bộ điều hướng?
William

@William bạn làm tôi cười hahaha. Câu trả lời của anh chàng này nên được đánh giá thấp.
Karim Manaouil

-7

Lỗi đã biến mất sau khi tôi thực hiện Clean-> Run xDoclet-> Run xPackaging.

Trong không gian làm việc của tôi, trong nhật thực.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.