【问题标题】:What could cause java.lang.reflect.InvocationTargetException?什么可能导致 java.lang.reflect.InvocationTargetException?
【发布时间】:2011-08-26 14:47:55
【问题描述】:

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

我的代码中有这个:

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

事情是,当它试图调用某个方法时,它会抛出 InvocationTargetException 而不是其他一些预期的异常(特别是 ArrayIndexOutOfBoundsException)。 因为我实际上知道调用了什么方法,所以我直接进入了这个方法代码,并为应该抛出 ArrayIndexOutOfBoundsException 的行添加了一个 try-catch 块,它确实像预期的那样抛出了 ArrayIndexOutOfBoundsException。然而上去的时候 以某种方式更改为InvocationTargetException 和上面的代码catch(Exception e) e 是 InvocationTargetException 而不是 ArrayIndexOutOfBoundsException 正如预期的那样。

什么可能导致这种行为或者我如何检查这种情况?

【问题讨论】:

  • 我遇到了同样的问题,只是我很久没有意识到这是一个调用目标异常......

标签: java exception reflection invoke


【解决方案1】:

您通过使用反射调用方法添加了额外的抽象级别。反射层将任何异常包装在 InvocationTargetException 中,这样您就可以区分由反射调用失败引起的异常实际上之间的区别(例如,您的参数列表可能无效)以及调用的方法中的故障。

只需解开 InvocationTargetException 中的原因,您就会找到原来的原因。

【讨论】:

  • @user550413:当然,通过打开异常并检查它。你总是可以自己扔它,如果必须的话,可以用这种方式接住它。
  • 对于任何想知道“在InvocationTargetException 中解开原因”意味着什么的人,我刚刚发现如果您使用exception.printStackTrace() 打印它,您只需查看“导致By:" 部分而不是上半部分/正常部分。
  • 要添加关于“展开”的解释,您还可以捕获异常并对其使用 getCause() 方法,如果需要,也可以重新抛出该异常。类似try {...} catch (InvocationTargetException ex) { log.error("oops!", ex.getCause()) }...catch... { throw ex.getCause() }
  • +1 @HJanrs for you just look at the "Caused By:" section instead of the top half/normal section
  • @DheraajBhaskar 不要像编辑自己的答案一样编辑其他人的答案,也不要对未引用的文本使用引号格式。该编辑应该已作为评论发布。
【解决方案2】:

如果发生异常则抛出

InvocationTargetException - 如果底层方法抛出异常。

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

【讨论】:

  • 很好的解释!
  • 如果我期望底层方法抛出异常怎么办?我应该抓住这个异常并简单地重新抛出吗?
【解决方案3】:

使用InvocationTargetException 上的getCause() 方法检索原始异常。

【讨论】:

    【解决方案4】:

    来自 Method.invoke() 的 Javadoc

    Throws: InvocationTargetException - 如果底层方法抛出异常。

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

    【讨论】:

    • 所以想象一下我有一个级联的java.lang.reflect.Proxy 实例来扩充一个包装的对象。每个Proxy 都使用自己的InvocationHandler 优雅地处理特定异常(可能由包装对象抛出)。对于通过此级联直到到达正确的调用处理程序/代理的异常,在每个InvocationHandler 中,我会捕获InvocationTargetException,打开它,检查包装的异常是否是instanceof 要处理的异常InvocationHandler。如果不是instanceof,我会抛出 unwrapped 异常...对吗?
    • 我总是会抛出未包装的异常。
    【解决方案5】:

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

    try {
    
        // try code
        ..
        m.invoke(testObject);
        ..
    
    } catch (InvocationTargetException e) {
    
        // Answer:
        e.getCause().printStackTrace();
    } catch (Exception e) {
    
        // generic exception handling
        e.printStackTrace();
    }
    

    【讨论】:

    • 谢谢;这帮助我意识到我的问题不在于反射本身,而在于调用的方法。
    【解决方案6】:

    InvocationTargetException 可能正在结束您的ArrayIndexOutOfBoundsException。使用反射时没有预先说明该方法会抛出什么——因此,与其使用throws Exception 方法,不如将所有异常都捕获并封装在InvocationTargetException 中。

    【讨论】:

    • 谢谢,但是我在 (AssertionError e) 和 (Exception e) 之间有什么区别?如果我总是先得到 InvocationTargetException,然后再解开原因,那么每个异常之间的区别在哪里?
    【解决方案7】:

    This 描述类似,

    InvocationTargetException 是一个检查异常,它包装了一个 被调用的方法或构造函数抛出的异常。发布时 从 1.4 开始,此异常已被改进以符合通用异常链机制。 “目标异常”是 在施工时提供并通过 getTargetException() 方法现在被称为原因,并且可能是 通过 Throwable.getCause() 方法以及 前面提到的“遗留方法”。

    【讨论】:

      【解决方案8】:

      您可以像这样使用 getCause() 方法与原始异常类进行比较:

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

      【讨论】:

        【解决方案9】:

        在我的class 中的try / catch 块中调用外部class 中的记录器对象的语句出现java.lang.reflect.InvocationTargetException 错误。

        单步执行 Eclipse 调试器中的代码并将鼠标悬停在记录器语句上,我看到记录器 objectnull(一些外部常量需要在我的 class 的最顶部实例化)。

        【讨论】:

          【解决方案10】:

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

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

          【讨论】:

            【解决方案11】:

            我也遇到了同样的问题。我使用了 e.getCause().getCause() 然后我发现这是因为我传递的参数错误。获取参数之一的值时出现 nullPointerException。 希望这会对你有所帮助。

            【讨论】:

              【解决方案12】:

              一个问题也可能是 targetSdkVersion 已提高并且您使用了已弃用的 Gradle 清单功能。再次尝试降低 targetSdkVersion 并查看它是否有效。就我而言,它是 targetSdkVersion 31 -> 30

              【讨论】:

                【解决方案13】:
                1. 在 Eclipse Navigator 模式下列出所有 jar 文件
                2. 验证所有 jar 文件是否为二进制模式

                【讨论】:

                • 您如何通过在导航器中查看 jar 文件来验证它们是否处于二进制模式?
                • @William 你让我笑了哈哈哈。这个人的回答应该被否决。
                【解决方案14】:

                我这样做后错误消失了 清理->运行 xDoclet->运行 xPackaging。

                在我的工作区,在日食中。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-18
                  • 2018-03-16
                  • 1970-01-01
                  相关资源
                  最近更新 更多