1. Overview

When working with Java Reflection API, it is common to encounter java.lang.reflect.InvocationTargetException.

In this tutorial, we’ll take a look at it and how to handle it with a simple example*.*

2. Cause of InvocationTargetException

It mainly occurs when we work with the reflection layer and try to invoke a method or constructor that throws an underlying exception itself.

The reflection layer wraps the actual exception thrown by the method with the InvocationTargetException.

Let’s try to understand it with an example.

We’ll write a class with a method that intentionally throws an exception:

public class InvocationTargetExample {
    public int divideByZeroExample() {
        return 1 / 0;
    }
}

Let’s invoke the above method using reflection in a Simple JUnit 5 Test:

InvocationTargetExample targetExample = new InvocationTargetExample(); 
Method method =
  InvocationTargetExample.class.getMethod("divideByZeroExample");
 
Exception exception =
  assertThrows(InvocationTargetException.class, () -> method.invoke(targetExample));

In the above code, we have asserted the InvocationTargetException, which is thrown while invoking the method. An important thing to note here is that the actual exception — ArithmeticException in this case — gets wrapped into an InvocationTargetException.

Now, why doesn’t reflection throw the actual exception in the first place?

The reason is that it allows us to understand whether the Exception occurred due to failure in calling the method through the reflection layer or whether it occurred within the method itself.

3. How to Handle InvocationTargetException?

Here the actual underlying exception is the cause of InvocationTargetException, so we can use Throwable.getCause() to get more information about it.

Let’s see how we can use getCause() to get the actual exception in the same example used above:

assertEquals(ArithmeticException.class, exception.getCause().getClass());

We’ve used the getCause() method on the same exception object that was thrown. And we have asserted ArithmeticException.class as the cause of the exception.

So, once we get the underlying exception, we can re-throw the same, wrap it in some custom exception or simply log the exception based on our requirement.

4. Conclusion

In this short article, we saw how the reflection layer wraps any underlying exception.

We also saw how to determine the underlying cause of the InvocationTargetException and how to handle such a scenario with a simple example.

As usual, the code used in this article is available over on GitHub.