什么会导致java.lang.reflect.InvocationTargetException?


313

好吧,我试图理解并阅读可能导致它的原因,但是我却无法理解:

我的代码中有这个地方:

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

事实是,当它尝试调用某个方法时,它会抛出InvocationTargetException而不是其他预期的异常(特别是ArrayIndexOutOfBoundsException)引发 。我实际上知道调用了什么方法,所以我直接转到此方法代码,并为假定要抛出的行添加了一个try-catch块 ArrayIndexOutOfBoundsException,它确实ArrayIndexOutOfBoundsException按预期抛出了。然而,当它上升时,以某种方式InvocationTargetExceptioncatch(Exception e) e 上面的代码中进行更改是InvocationTargetExceptionArrayIndexOutOfBoundsException 符合预期的。

是什么原因导致这种行为的?我该如何检查?

Answers:


333

通过使用反射调用方法,您已经添加了额外的抽象级别。反射层将任何异常包装在中InvocationTargetException,该异常可让您分辨出反射调用失败(例如,您的参数列表无效)实际导致的异常与所调用方法中的失败之间的区别。

只需解开内的原因InvocationTargetException,您就可以找到原始原因。


4
@ user550413:当然,通过展开异常并进行检查。您始终可以自己扔掉它,并在必要时以这种方式捕获它。
乔恩·斯基特

157
对于任何想知道“将原因拆开”是什么意思的人InvocationTargetException,我只是发现,如果您使用进行了打印exception.printStackTrace(),则只需查看“ Caused By:”部分,而不是上半部/正常部分。
1

31
要添加有关“展开”的说明,您还可以捕获异常并在其上使用getCause()方法,如果需要,也可以将其重新抛出。类似于try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }...catch... { throw ex.getCause() }
jcadcell 2012年

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

1
@DheraajBhaskar不要像别人一样编辑别人的答案,也不要对未加引号的文本使用引号格式。该修改应已发布为评论。
洛恩侯爵,2015年

51

如果抛出异常

InvocationTargetException-如果基础方法引发异常。

因此,如果已由反射API调用的方法抛出异常(例如运行时异常),则反射API会将异常包装为InvocationTargetException


很好的解释!
gaurav '19

如果我期望基础方法抛出异常怎么办?我应该抓住这个例外并简单地重新抛出吗?
jDub9


21

来自Method.invoke()的Javadoc

抛出:InvocationTargetException-如果基础方法抛出异常。

如果调用的方法引发异常,则抛出此异常。


因此,想象一下我有一系列java.lang.reflect.Proxy实例来增强包装对象。每Proxy一个都通过使用自己的优雅地处理特定的异常(可能由包装的对象抛出)InvocationHandler。对于一个遍历此级联直到到达正确的调用处理程序/代理的异常,在每个异常中InvocationHandler,我都将捕获InvocationTargetException,解开该异常,检查包装的异常是否是instanceof要由this处理的异常InvocationHandler。如果不是instanceof,我会抛出未包装的异常...对吗?
Abdull

我总是会抛出未包装的异常。
彼得·劳瑞

9

InvocationTargetException可能是包裹了你的ArrayIndexOutOfBoundsException。在使用反射时,没有预先告知该方法可以引发什么—因此,不是使用一种throws Exception方法,而是捕获了所有异常并将其包装在中InvocationTargetException


谢谢,但是例如,我在(AssertionError e)和(Exception e)之间有什么区别?如果在展开原因之前始终总是先获取InvocationTargetException,那么每个异常之间的区别在哪里?
user550413 2011年

9

这将在特定方法中打印确切的代码行,该方法在调用时会引发异常:

try {

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

} catch (InvocationTargetException e) {

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

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

1
谢谢; 这使我意识到我的问题不在反射本身中,而是在调用的方法中。
JoseGómez'17

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的外部调用logger对象的语句出错。classtrycatchclass

通过代码在Eclipse调试器步进及以上只见记录器记录的语句将鼠标objectnull(需要一些外部的常量在我的最顶部被实例化class)。


0

如果基础方法(使用反射调用的方法)抛出异常,则抛出此异常。

因此,如果已由反射API调用的方法抛出异常(例如运行时异常),则反射API会将异常包装到InvocationTargetException中。


0

我面临着同样的问题。我使用了e.getCause()。getCause(),然后发现这是因为我传递的参数错误。获取参数之一的值时存在nullPointerException。希望这会帮助你。


-2
  1. 列出Eclipse Navigator模式下的所有jar文件
  2. 验证所有jar文件都处于二进制模式

4
通过在导航器中查看jar文件,您如何准确地验证jar文件处于二进制模式?
威廉

@威廉,你让我笑哈哈哈。这个家伙的答案应该被否决了。
卡里姆·马纳维尔

-7

在执行Clean-> Run xDoclet-> Run xPackaging之后,错误消失了。

在我的工作区中,日蚀。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.