抛出异常的哪一部分是昂贵的? [英] Which part of throwing an Exception is expensive?

查看:150
本文介绍了抛出异常的哪一部分是昂贵的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,当没有实际的错误时,使用throw / catch作为逻辑的一部分通常是一个坏主意(部分原因),因为抛出和捕获异常是昂贵的,并且在循环中执行多次通常是很远的比其他不涉及抛出异常的控制结构更慢。



我的问题是,在throw / catch本身或创建Exception对象时产生的成本(因为它获得了大量的运行时信息,包括执行堆栈)?



换句话说,如果我做

 异常e = new Exception(); 

但不要扔它,是大部分投掷的成本,还是抛出+处理什么是昂贵的?



我不是问是否将代码放在try / catch块中增加了执行代码的代价,我在问是否捕捉异常是昂贵的部分,或创建(调用构造函数)异常是昂贵的部分。



另一种提出这个问题的方法是,如果我做了一个异常实例并抛出一次又一次的抓住它,这会比每次抛出一个新的异常快得多吗?

解决方案

strong>创建异常对象不会比创建其他常规对象更昂贵。主要费用隐藏在本机 fillInStackTrace中 方法,它们遍历调用堆栈并收集所有需要的信息以构建堆栈跟踪:类,方法名称,行号等。



关于高异常成本的神话来自于大多数 Throwable 构造函数隐含地调用 fillInStackTrace 。但是,有一个构造函数创建一个没有堆栈跟踪的 Throwable 。它允许您制作非常快速实例化的可抛弃物。另一种创建轻量级异常的方法是覆盖 fillInStackTrace






现在,抛出一个异常?

其实这取决于抛出的异常是捕获的



如果它被捕获在相同的方法中(或者更确切地说,在相同的上下文中,因为上下文可能包括几个方法,因为内联),那么 throw goto (当然是在JIT编译之后)一样简单。



但是如果 catch 块在堆栈的更深处,则JVM需要展开堆栈帧,这可能需要更长的时间。如果存在同步块或方法,则需要更长时间,因为展开意味着释放由已移除的堆栈框架拥有的显示器。






我可以通过适当的基准确认上述语句,但幸运的是我不需要这样做,因为HotSpot性能的所有方面已经完全覆盖工程师AlexeyShipilëv: Lil'Exception的卓越表现


In Java, using throw/catch as a part of logic when there's not actually an error is generally a bad idea (in part) because throwing and catching an exception is expensive, and doing it many times in a loop is usually far slower than other control structures which don't involve throwing exceptions.

My question is, is the cost incurred in the throw/catch itself, or when creating the Exception object (since it gets a lot of runtime information including the execution stack)?

In other words, if I do

Exception e = new Exception();

but don't throw it, is that most of the cost of throwing, or is the throw + catch handling what's costly?

I'm not asking whether putting code in a try/catch block adds to the cost of executing that code, I'm asking whether catching the Exception is the expensive part, or creating (calling the constructor for) the Exception is the expensive part.

Another way of asking this is, if I made one instance of Exception and threw and caught it over and over, would that be significantly faster than creating a new Exception every time I throw?

解决方案

Creating an exception object is not more expensive than creating other regular objects. The main cost is hidden in native fillInStackTrace method which walks through the call stack and collects all required information to build a stack trace: classes, method names, line numbers etc.

The myth about high exception costs comes from the fact that most of Throwable constructors implicitly call fillInStackTrace. However, there is one constructor to create a Throwable without a stack trace. It allows you to make throwables that are very fast to instantiate. Another way to create lightweight exceptions is to override fillInStackTrace.


Now what about throwing an exception?
In fact, it depends on where a thrown exception is caught.

If it is caught in the same method (or, more precisely, in the same context, since the context can include several methods due to inlining), then throw is as fast and simple as goto (of course, after JIT compilation).

However if a catch block is somewhere deeper in the stack, then JVM needs to unwind the stack frames, and this can take significantly longer. It takes even longer, if there are synchronized blocks or methods involved, because unwinding implies releasing of monitors owned by removed stack frames.


I could confirm the above statements by proper benchmarks, but fortunately I don't need to to this, since all the aspects are already perfectly covered in the post of HotSpot performance engineer Alexey Shipilëv: The Exceptional Performance of Lil' Exception.

这篇关于抛出异常的哪一部分是昂贵的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆