在 Java 中,当实际上没有错误时,使用 throw/catch 作为逻辑的一部分通常是一个坏主意(部分),因为抛出和捕获异常的成本很高,并且在循环中多次执行通常比其他方法慢得多不涉及抛出异常的控制结构。
我的问题是,成本是在 throw/catch 本身中产生的,还是在创建 Exception 对象时产生的(因为它获取了大量运行时信息,包括执行堆栈)?
换句话说,如果我这样做
Exception e = new Exception();
但不要扔它,这是扔的大部分成本,还是扔+捕获处理的成本高?
我不是在问将代码放入 try/catch 块中是否会增加执行该代码的成本,而是在问捕获异常是否是昂贵的部分,或者创建(调用其构造函数)异常是昂贵的部分。
提出这个问题的另一种方式是,如果我创建一个 Exception 实例并一遍又一遍地抛出和捕获它,这会比每次抛出时创建一个新的 Exception 快得多吗?
Creating异常对象不是一定比创建其他常规对象更昂贵。主要成本隐藏在原生成本中fillInStackTrace方法遍历调用堆栈并收集构建堆栈跟踪所需的所有信息:类、方法名称、行号等。
Most of Throwable
构造函数隐式调用fillInStackTrace
。这就是创建异常很慢的想法的由来。然而,有一个构造函数创建一个Throwable
没有堆栈跟踪。它允许您制作可快速实例化的可抛出对象。创建轻量级异常的另一种方法是重写fillInStackTrace
.
现在呢throwing例外吗?
事实上,这取决于抛出异常的位置caught.
如果它被捕获在同一个方法中(或者更准确地说,在同一个上下文中,因为上下文可以由于内联而包含多个方法),那么throw
既快速又简单goto
(当然是在JIT编译之后)。
然而,如果一个catch
块位于堆栈较深处的某个位置,那么 JVM 需要展开堆栈帧,这可能需要更长的时间。如果有的话,需要更长的时间synchronized
涉及的块或方法,因为展开意味着释放已删除的堆栈帧所拥有的监视器。
我可以通过适当的基准来确认上述陈述,但幸运的是我不需要这样做,因为所有方面都已经在 HotSpot 的性能工程师 Alexey Shipilev 的帖子中完美地涵盖了:Lil' Exception 的卓越表现.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)