0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用try-catch捕获异常会影响性能吗?

小林coding 来源:yes的练级攻略 2023-04-01 11:08 次阅读

“你看着这鬼代码,竟然在 for 循环里面搞了个 try-catch,不知道try-catch有性能损耗吗?”

老陈煞有其事地指着屏幕里的代码:

for(inti=0;i< 5000; i++) {
     try {
         dosth
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

我探过头去看了眼代码,“那老陈你觉得该怎么改?”

“当然是把 try-catch 提到外面啊!”老陈脑子都不转一下,脱口而出。

“你是不是傻?且不说性能,这代码的目的明显是让循环内部单次调用出错不影响循环的运行,你其到外面业务逻辑不就变了吗!”

老陈挠了挠他的地中海,“好像也是啊!”

“回过头来,catch 整个 for 循环和在循环内部 catch,在不出错的情况下,其实性能差不多。” 我喝一口咖啡不经意地提到,准备在老陈前面秀一下。

“啥意思?”老陈有点懵地看着我,“try-catch是有性能损耗的,我可是看过网上资料的!”

果然,老陈上钩了,我二话不说直接打开 idea,一顿操作敲了以下代码:

publicclassTryCatchTest{

@Benchmark
publicvoidtryfor(Blackholeblackhole){
try{
for(inti=0;i< 5000; i++) {
                blackhole.consume(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Benchmark
    public void fortry(Blackhole blackhole) {
        for (int i = 0; i < 5000; i++) {
            try {
                blackhole.consume(i);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

“BB 不如 show code,看到没,老陈,我把 try-catch 从 for 循环里面提出来跟在for循环里面做个对比跑一下,你猜猜两个差多少?”

“切,肯定 tryfor 性能好,想都不用想,不是的话我倒立洗头!”老陈信誓旦旦道。

我懒得跟他BB,直接开始了 benchmark,跑的结果如下:

600c01bc-bb5d-11ed-bfe3-dac502259ad0.png

可以看到,两者的性能(数字越大越好)其实差不多:

fortry: 86,261(100359-14098) ~ 114,457(100359+14098)

tryfor: 95,961(103216-7255) ~ 110,471(103216+7255)

我再调小(一般业务场景 for 循环次数都不会很多)下 for 循环的次数为 1000 ,结果也是差不多:

6023335a-bb5d-11ed-bfe3-dac502259ad0.png

老陈一看傻了:“说好的性能影响呢?怎么没了?”

我直接一个javap,让老陈看看,其实两个实现在字节码层面没啥区别:

tryfor 的字节码

异常表记录的是 0 - 20 行,如果这些行里面的代码出现问题,直接跳到 23 行处理。

603a6c1e-bb5d-11ed-bfe3-dac502259ad0.png

fortry 的字节码

差别也就是异常表的范围小点,包的是 9-14 行,其它跟 tryfor 都差不多。

60bda0fc-bb5d-11ed-bfe3-dac502259ad0.png图片

所以从字节码层面来看,没抛错两者的执行效率其实没啥差别。

“那为什么网上流传着try-catch会有性能问题的说法啊?”老陈觉得非常奇怪。

这个说法确实有,在《Effective Java》这本书里就提到了 try-catch 性能问题:

61350138-bb5d-11ed-bfe3-dac502259ad0.png

并且还有下面一段话:

615dbf10-bb5d-11ed-bfe3-dac502259ad0.png图片

正所谓听话不能听一半,以前读书时候最怕的就是一知半解,因为完全理解选择题能选对,完全不懂蒙可能蒙对,一知半解必定选到错误的选项!

《Effective Java》书中说的其实是不要用 try-catch 来代替正常的代码,书中的举例了正常的 for 循环肯定这样实现:

6196087a-bb5d-11ed-bfe3-dac502259ad0.png

但有个卧龙偏偏不这样实现,要通过 try-catch 拐着弯来实现循环:

61a86c7c-bb5d-11ed-bfe3-dac502259ad0.png

这操作我只能说有点逆天,这两个实现的对比就有性能损耗了。

我们直接再跑下有try-catch 的代码和没 try-catch的 for 循环区别,代码如下:

6202e3e6-bb5d-11ed-bfe3-dac502259ad0.png

结果如下:

621415ee-bb5d-11ed-bfe3-dac502259ad0.png

+-差不多,直接看前面的分数对比,没有 ry-catch 的性能确实好些,这也和书中说的 try-catch 会影响 JVM 一些特定的优化说法吻合,但是具体没有说影响哪些优化,我猜测可能是指令重排之类的。

好了,我再总结下有关 try-catch 性能问题说法

try-catch 相比较没 try-catch,确实有一定的性能影响,但是旨在不推荐我们用 try-catch 来代替正常能不用 try-catch 的实现,而不是不让用 try-catch。

for循环内用 try-catch 和用 try-catch 包裹整个 for 循环性能差不多,但是其实两者本质上是业务处理方式的不同,跟性能扯不上关系,关键看你的业务流程处理。

虽然知道try-catch会有性能影响,但是业务上不需要避讳其使用,业务实现优先(只要不是书中举例的那种逆天代码就行),非特殊情况下性能都是其次,有意识地避免大范围的try-catch,只 catch 需要的部分即可(没把握全 catch 也行,代码安全执行第一)。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2916

    浏览量

    103350
  • JVM
    JVM
    +关注

    关注

    0

    文章

    152

    浏览量

    12145

原文标题:支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!

文章出处:【微信号:小林coding,微信公众号:小林coding】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    一站式统一返回值封装、异常处理、异常错误码解决方案—最强的Sping Boot接口优雅响应处理器

    处理的逻辑集中到一个地方,避免代码中出现大量的try-catch语句,降低了代码的复杂度,提高了代码的可读性;异常体系的设计可以清晰地区分不同类型的异常,使得开发者能够更加精准地处理异常
    的头像 发表于 06-20 15:42 139次阅读

    鸿蒙原生应用开发-ArkTS语言基础类库异步并发简述async/await

    块来捕获异步操作中的异常。 async function myAsyncFunction() { try { const result = await new Promise((resolve
    发表于 03-06 14:44

    介绍C语言中错误处理和异常处理的一些常用的方法和策略

    C语言是一种低级的、静态的、结构化的编程语言,它没有提供像C++或Java等高级语言中的异常处理机制,例如try-catch-finally等。
    的头像 发表于 02-28 14:25 349次阅读

    大功率磁环电感发热异常会影响使用吗

    电子发烧友网站提供《大功率磁环电感发热异常会影响使用吗.docx》资料免费下载
    发表于 01-23 10:04 0次下载

    TCPWM输入脉宽捕获数据异常的原因?

    您好,最近尝试使用TCPWM实现脉宽捕获的时候遇到了奇怪的问题,我将通道配置成了捕获模式,并且配置CC0为上升沿捕获,CC1为下降沿捕获,但观察实际值却是CC0和CC1一同刷新了,这是
    发表于 01-18 07:42

    一个通道如何捕获PWM的频率和占空比?

    一,前言正常情况是双通道捕获PWM波,这种方法简单且准确,但是它占用的资源太多了,因为它使用定时器的两个通道,且这两个通道映射在一个通道上,同时配置一路捕获为触发定时器复位,所以只能使用2个通道
    的头像 发表于 12-30 08:00 713次阅读
    一个通道如何<b class='flag-5'>捕获</b>PWM的频率和占空比?

    燃油系统压力异常会导致什么故障现象

    燃油系统压力异常可能导致多种问题和故障,因为正常的燃油压力对引擎性能至关重要。
    的头像 发表于 12-12 11:15 464次阅读
    燃油系统压力<b class='flag-5'>异常会</b>导致什么故障现象

    TRY推拉力测试机有什么原理与应用领域

    TRY推拉力测试机有什么原理与应用领域
    的头像 发表于 11-23 09:07 357次阅读
    <b class='flag-5'>TRY</b>推拉力测试机有什么原理与应用领域

    Python 怎么捕获警告(Warning)?

    不然,异常和错误,都是程序出现了一些问题,但是警告不同,他的紧急程度非常之低,以致于大多数的警告都是可以直接忽略的。 如果不想显示这些告警信息,可以直接加上参数 -W ignore 参数,就不会再显示了。 2. 警告能捕获吗 能捕获
    的头像 发表于 11-01 10:57 613次阅读
    Python 怎么<b class='flag-5'>捕获</b>警告(Warning)?

    Spring Boot怎么通过注解来实现全局异常处理的

    前言 在平时的 API 开发过程中,总会遇到一些错误异常没有捕捉到的情况。那有的小伙伴可能会想,这还不简单么,我在 API 最外层加一个 try...catch 不就完事了。 哈哈哈,没错。这种
    的头像 发表于 10-13 10:58 472次阅读
    Spring Boot怎么通过注解来实现全局<b class='flag-5'>异常</b>处理的

    什么是凹槽效应?什么原因引起的?怎么抑制这种异常效应呢?

    在刻蚀SOI衬底时,通常会发生一种凹槽效应,导致刻蚀的形貌与预想的有很大出入。那么什么是凹槽效应?什么原因引起的?怎么抑制这种异常效应呢?
    的头像 发表于 10-11 18:18 1258次阅读
    什么是凹槽效应?什么原因引起的?怎么抑制这种<b class='flag-5'>异常</b>效应呢?

    2012 款宝马 X6 xDrive35i 车 中央显示屏经常会提示“发动机异常

    一辆2012 款宝马X6 xDrive35i车(开发系列号为E71),搭载N55发动机,累计行驶里程约为21.2万km。车主反映,车辆加速过程中,中央显示屏经常会提示“发动机异常”。
    的头像 发表于 10-11 09:26 473次阅读
    2012 款宝马 X6 xDrive35i 车 中央显示屏经<b class='flag-5'>常会</b>提示“发动机<b class='flag-5'>异常</b>”

    基于rt_thread实现c语言的try catch finally捕获崩溃错误代码

    支持捕捉空指针访问,未对齐操作,除零崩溃,等等错误,帮助你高效调试代码.
    的头像 发表于 09-27 11:47 455次阅读

    try catch应该在for循环里面还是外面?

    因为本身try catch 放在 for循环 外面 和里面 ,如果出现异常,产生的效果是不一样的。
    的头像 发表于 07-31 10:16 810次阅读
    <b class='flag-5'>try</b> <b class='flag-5'>catch</b>应该在for循环里面还是外面?

    STM32定时器(三)输入捕获

    STM32的定时器是支持信号输入捕获的,何为输入捕获?主要做什么应用?
    的头像 发表于 07-21 14:58 3201次阅读
    STM32定时器(三)输入<b class='flag-5'>捕获</b>