重新抛出 Java 异常与使用 instanceof/cast 的开销

Nic*_*ick 3 java performance exception executionexception

我知道 Java 异常的开销已经在 SO 上搞砸了,但我没有找到任何可以解决我的情况的东西。我有一个 Future,它在调用 get() 时可能会抛出一个包含任意数量的特定于应用程序的异常的 ExecutionException。我想知道使用看起来更好的 try-catch 块而不是丑陋的 if-instanceof-then-cast 模式是否会产生显着的开销。例如,它可能看起来像这样:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

我的理论是,不应该有大量的开销,因为

  • 异常和堆栈跟踪已经构造完毕。
  • 无论如何,我都在这两种方法中对异常对象执行反射。
  • 异常会被立即捕获并且不会传播。

Mik*_*bel 5

就风格而言,我通常建议不要对常规控制流使用异常处理程序。不过,我可以在这里看到使用它的论据,因为 的设计Future要求您“解开”原始异常。

重新抛出异常应该比抛出新异常便宜得多,因为堆栈跟踪已经被填充。第一种方法可能仍然会产生更多开销,但如果您的应用程序抛出如此多的异常,以至于影响变得明显,那么您可能会遇到更大的问题。

如果这确实是您关心的问题,那么您获得有意义答案的唯一方法就是亲自衡量差异。但是,同样,只有在特殊情况下才应该抛出异常;它们在设计上应该是不常见的。即使将异常处理的成本加倍,成本也仅为2n而不是n。如果您抛出如此多的异常,导致应用程序的性能明显受到影响,那么简单的两个因素可能不会让您成功或失败。因此,请使用您认为更具可读性的样式。