Java try / catch性能,是否建议将try子句中的内容保持在最低限度?

Java try/catch performance, is it recommended to keep what is inside the try clause to a minimum?

考虑到你有这样的代码:

1
2
3
4
doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing the same kind of exceptions.

现在我知道了,在构造异常时,实际上有一个性能问题,特别是在展开堆栈时。我还阅读了几篇文章,指出在进入try/catch块时性能会受到轻微影响,但这些文章似乎都没有得出任何结论。

我的问题是,是否建议将try catch中的行保持在最低限度?也就是说,只在try子句中包含可以实际引发您捕获的异常的行。try子句中的代码是否运行较慢或导致性能下降?.

但更重要的是,考虑到这一点,最佳实践/更具可读性的解决方案是什么:

1
2
3
4
5
6
7
8
9
try {
    doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing the same kind of exceptions.
}
catch (MyCheckedException e) {
   //handle it
}

或:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
try {
    doSomething() // this method may throw a checked a exception
}
catch (MyCheckedException e) {
   //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
   continue;    
}
 //do some assignements calculations
try {
    doAnotherThing() // this method may throw a checked a exception
}
catch (MyCheckedException e) {
    //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
   continue;
}

这考虑到您将以完全相同的方式处理所有这些检查过的异常。


Is it recommended to keep the lines
inside the try catch to bare minimum?

不。无法想象您如何认为try块的长度或任何块的长度会对性能产生任何影响。

Does the code inside the try clause
run slower or cause any performance
hit?.

不。

正如您所观察到的,异常只会在抛出时产生性能成本。

如果您担心"尝试"性能,那么一定要将代码保持在最大限度内?


在这里的示例中,如果dosomething()和doanotherthing()都抛出异常,则会真正影响性能。输入try块很快,直到它抛出异常为止。

这真的取决于你的处境。如果在以任何一种方式抛出mycheckedException时需要执行相同的操作,我会认为将它们放在同一个try块中更具可读性和性能,但是如果您需要以不同的方式处理这两种不同的情况,那么将它们分开当然更有意义。

编辑:我阅读了您的评论的结尾,您假设以相同的方式处理这两个问题,在这种情况下,我将把它们放在同一个try块中。


我不确定哪一个更慢,但不要忘记,try块是控制流。您应该使控制流与您试图实现的目标相匹配。对我来说,选择

1
2
3
4
5
6
7
8
9
10
try {
    // op 1.
    // op 2.
    / ...
    // op n.
}
catch ( MyCheckedException error )
{
    // handle any `MyException` in op 1, 2 ... n.
}

每个单独的catch块主要是决定我是否要对每个op做不同的处理,继续执行到opn为止,无论是否有错误,或者尝试执行所有错误,并在第一个错误时失败。

编写清晰易读的代码,然后搜索瓶颈。如果现有的实验不能得出基本准则的结论,那么我怀疑这并不是你找到瓶颈的地方。


在任何一个合适的JVM中,拥有try块基本上都没有性能影响。真正的打击发生在实际抛出异常时。

您可以阅读本文了解JVM如何在字节码中实现异常处理:它创建"异常表",将代码区域映射到catch/finally块,因此:

  • try块的字节码与标准块的字节码相同。
  • 在非抛出的情况下,唯一额外的开销是在内存中加载"异常表"。

当然,当抛出一个异常时,会有大量的堆栈工作在进行,所以会有成本。不管怎样,它并没有SEH(净异常)那么糟糕。


您的代码应该只处理它可以做些什么的异常,其他的应该被重新抛出。

try块中的代码量不会导致速度变慢,而命中catch块则会导致速度变慢。但是,除非您尝试编写真正的高性能代码,否则我不会担心它。


将try/catch块的数量保持在最小将略微提高性能,但移动工作并不会真正产生影响,除非由于引发异常而跳过工作。


异常成本很高,因为每次抛出异常时,都必须创建和填充堆栈跟踪。

设想一个余额转移操作在1%的情况下由于资金不足而失败。即使故障率相对较低,性能也可能受到严重影响。

请参见此处的源代码和基准测试结果。


我不确定在try块中,性能可能很慢,但我知道ex.getStackTrace()的性能非常慢,因为它显示了所有的命令堆栈,您应该小心。


每个异常块都有开销。所以,你想最大限度地延长你呆在一个街区的时间。

但是,您还必须考虑语义上的差异。在第一个示例中,如果doSomething()抛出异常,那么doAnotherThing()将不会运行。在第二个示例中(假设catch处理程序不返回),将运行doAnotherThing()