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.
Let's write a class with a method that intentionally throws an exception:
public class InvocationTargetExample { public int divideByZeroExample() { return 1 / 0; } }
Now, 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 wraped into an InvocationTargetException.
Now, the question that comes to mind is, 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());
Here, 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've seen how the reflection layer wraps any underlying exception. We have also seen 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.