java.lang.reflect.InvocationTargetExceptionの原因は何ですか?


313

まあ、私はそれを引き起こす可能性があるものを理解して読んでみましたが、それを得ることができません:

私のコードのどこかにこれがあります:

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

それは、あるメソッドを呼び出そうとするInvocationTargetExceptionと、他の予期される例外(具体的にはArrayIndexOutOfBoundsException)の代わりにスロー されるということです。呼び出されるメソッドを実際に知っているので、このメソッドコードに直接進み、スローするはずの行にtry-catchブロックを追加しましたArrayIndexOutOfBoundsExceptionArrayIndexOutOfBoundsException、期待どおりに実際にスロー されました。それでも上に行くと、どういうわけかInvocationTargetException、上記のコードに変更され、catch(Exception e) eは 予想どおりではInvocationTargetExceptionありませんArrayIndexOutOfBoundsException

何がそのような動作を引き起こす可能性がありますか、またはどのようにしてそのようなことを確認できますか?

回答:


333

リフレクションを使用してメソッドを呼び出すことにより、抽象化のレベルを追加しました。リフレクションレイヤーは例外をでラップInvocationTargetExceptionします。これにより、リフレクション呼び出しの失敗によって実際に引き起こされた例外(たとえば、引数リストが無効であった可能性があります)と呼び出されたメソッド内の失敗の違いを知ることができます。

内で原因を解明するだけで、元の原因に戻ることがInvocationTargetExceptionできます。


4
@ user550413:もちろん、例外をアンラップしてそれを調べることによって。あなたはいつでも自分で投げることができ、必要ならその方法でそれをキャッチすることができます。
ジョンスキート、

157
「原因を「内で解く」とはどういう意味かと思っている人のためにInvocationTargetException、を使用して印刷したexception.printStackTrace()場合は、上半分/通常のセクションではなく、「原因」セクションを確認するだけであることがわかりました。
1

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他の人の回答を自分のものであるかのように編集しないでください。引用されていないテキストには引用形式を使用しないでください。その編集はコメントとして投稿されているはずです。
ローンの侯爵2015

51

例外は次の場合にスローされます

InvocationTargetException-基本となるメソッドが例外をスローした場合。

したがって、リフレクションAPIで呼び出されたメソッドが例外(たとえば、ランタイム例外)をスローした場合、リフレクションAPIは例外をにラップしますInvocationTargetException


素晴らしい説明!
gaurav

基になるメソッドが例外をスローすると予想される場合はどうなりますか?この例外をキャッチして単純に再スローする必要がありますか?
jDub9


21

Method.invoke()のJavadocから

スロー:InvocationTargetException-基本となるメソッドが例外をスローした場合。

この例外は、呼び出されたメソッドが例外をスローした場合にスローされます。


java.lang.reflect.Proxyラップされたオブジェクトを強化するインスタンスのカスケードがあると想像してください。それぞれProxyが独自のを使用して、特定の例外(ラップされたオブジェクトによってスローされる可能性があります)を適切に処理しますInvocationHandler。例外がこのカスケードを介して波及して正しい呼び出しハンドラ/プロキシに到達するまで、それぞれでInvocationHandler、それをキャッチしInvocationTargetException、アンラップし、ラップされた例外がinstanceofthisによって処理される例外であるかどうかを確認しますInvocationHandler。それがでない場合instanceofラップされていない例外をスローします...
Abdull 2013

常にラップされていない例外をスローします。
Peter Lawrey 2013年

9

それはInvocationTargetExceptionおそらくあなたをラップしていますArrayIndexOutOfBoundsException。リフレクションを使用する場合、そのメソッドがスローできるものを事前に伝える必要はありません。そのため、throws Exceptionアプローチを使用する代わりに、すべての例外がキャッチされてにラップされInvocationTargetExceptionます。


ありがとうございます。しかし、たとえば(AssertionError e)と(Exception e)はどう違うのでしょうか。原因をアンラップする前に常にInvocationTargetExceptionを最初に取得する場合、各例外間でどこが異なるのですか?
user550413

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の外部のロガーオブジェクトを呼び出すステートメントからエラーが発生しましたclasstrycatchclass

Eclipseデバッガーでコードをステップ実行して、ロガーobjectが表示されているロガーステートメントの上にマウスを移動しますnull(いくつかの外部定数は、私の最上部でインスタンス化する必要がありましたclass)。


0

この例外は、基になるメソッド(Reflectionを使用して呼び出されたメソッド)が例外をスローした場合にスローされます。

したがって、リフレクションAPIによって呼び出されたメソッドが例外(たとえば、ランタイム例外)をスローした場合、リフレクションAPIは例外をInvocationTargetExceptionにラップします。


0

私も同じ問題に直面していました。e.getCause()。getCause()を使用したところ、渡したパラメーターが間違っていたことが原因であることがわかりました。パラメータの1つの値をフェッチするときにnullPointerExceptionがありました。これがお役に立てば幸いです。


-2
  1. Eclipseナビゲーターモードからすべてのjarファイルをリストする
  2. すべてのjarファイルがバイナリモードであることを確認します

4
ナビゲーターでそれらを表示して、jarファイルがバイナリモードであることをどのように正確に確認しますか?
ウィリアム

@ウィリアム、あなたは私を笑わせました。この男の答えは反対投票する必要があります。
Karim Manaouil、2018年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.