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

    文章

    2954

    浏览量

    104513
  • JVM
    JVM
    +关注

    关注

    0

    文章

    157

    浏览量

    12202

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

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

收藏 人收藏

    评论

    相关推荐

    是德DSOX4032A示波器波形捕获

    在电子工程领域,示波器是不可或缺的工具之一。而其中,是德DSOX4032A示波器以其卓越的性能和精准的测量能力备受青睐。今天,我们就来深入了解一下是德DSOX4032A示波器的波形捕获率。 一、波形
    的头像 发表于 08-30 15:38 218次阅读
    是德DSOX4032A示波器波形<b class='flag-5'>捕获</b>率

    HarmonyOS Next原生应用开发-从TS到ArkTS的适配规则(十四)

    类型,应省略类型标注。TypeScript try { // ... } catch (a: unknown) { // 处理异常 } ArkTS try { // ... }
    发表于 08-16 10:20

    esp8266在运行过程中,经常会出现复位异常的情况怎么解决?

    买的安可信的串口wifi模块, esp8266;可是发现在运行过程中,经常会出现复位异常的情况
    发表于 07-11 06:55

    工业自动化领域解决方案 利用Profishark工具捕获EtherCAT报文

    ProfiShark是一款高性能的报文捕获工具,专为工业网络设计,特别适用于EtherCAT报文的捕获与分析。通过高分辨率时间戳、100%高保真流量捕获、TSN支持及PoE直通功能
    的头像 发表于 07-05 14:01 290次阅读
    工业自动化领域解决方案 利用Profishark工具<b class='flag-5'>捕获</b>EtherCAT报文

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

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

    鸿蒙原生应用开发-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 585次阅读

    谈谈数字验证场景的“边界”和“异常

    在IC验证者进行测试点评审的时候,或者在和DE(数字设计工程师)、SE(系统工程师)进行验证场景讨论的时候,常常会听到“边界”“异常”这俩词。他俩就像是一对形影不离的好朋友,同时出现在验证者的耳畔和DE、SE的嘴边。
    的头像 发表于 01-23 13:43 703次阅读

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

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

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

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

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

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

    输电线路常见异常及处理原则

    输电线路常见异常及处理原则  输电线路是电力系统的重要组成部分,用于将发电厂产生的电能传输到用户。然而,在输电线路的正常运行过程中,常会出现一些异常情况,如断线、短路、过载等。正确处理这些异常
    的头像 发表于 12-18 15:47 1260次阅读

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

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

    Java怎么排查oom异常

    Java中的OOM(Out of Memory)异常是指当Java虚拟机的堆内存不足以容纳新的对象时抛出的异常。OOM异常是一种常见的运行时异常,经常出现在长时间运行的Java应用程序
    的头像 发表于 12-05 13:47 1203次阅读

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

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