Search code examples
javaperformanceexceptionexecutionexception

Overhead of rethrowing Java exception vs. using instanceof/cast


I know the overhead of Java exceptions has been done to death on SO, but I didn't find anything that addressed my situation. I have a Future, which upon calling get() might throw an ExecutionException containing any number of application-specific exceptions. I was wondering whether there is significant overhead using the nicer-looking try-catch block instead of the ugly if-instanceof-then-cast pattern. For example, it might look something like this:

private Response handleException(ExecutionException e) throws MyApplicationException {
  try {
    throw e.getCause();
  } catch (ApplicationException1 e1) {
    // known error
    throw MyApplicationException.convert(e1);
  } catch (ApplicationException2 e2) {
    // create error response
    return new Response(e2);
  } catch (Throwable t) {
    // unknown error
    throw new RuntimeException(t);
  }
}

private Response handleException2(ExecutionException e) throws MyApplicationException {
  Throwable cause = e.getCause();
  if (cause instanceof ApplicationException1) {
    ApplicationException1 e1 = (ApplicationException1) cause;
    throw MyApplicationException.convert(e1);
  } else if (cause instanceof ApplicationException2) {
    ApplicationException2 e2 = (ApplicationException2) cause;
    return new Response(e2);
  } else {
    throw new RuntimeException(cause);
  }
}

My theory is that there shouldn't be a huge amount of overhead since

  • The exception and stack trace have already been constructed.
  • I am performing reflection on the exception object in both methods anyway.
  • The exception is caught immediately and never propagated.

Solution

  • As as matter of style, I generally recommend not using exception handlers for regular control flow. I can see the argument for using it here, though, as the design of Future requires you to 'unwrap' the original exception.

    Rethrowing an exception should be substantially less expensive than throwing a new exception, as the stack trace has already been populated. There may still be more overhead with your first approach, but if your application is throwing so many exceptions that the impact becomes noticable, then you likely have bigger problems.

    If it's really a concern for you, the only way you'll get a meaningful answer is to measure the difference yourself. But, again, exceptions should only be thrown in exceptional cases; they should be uncommon by design. Even if you double the cost of exception handling, the cost is merely 2n instead of n. If you're throwing so many exceptions that your application's performance is suffering noticeably, a simple factor of two probably isn't going to make or break you. So use whichever style you find more readable.