“yes,你看着这鬼代码,竟然在 for 循环里边搞了个 try-catch,不知道try-catch有功能损耗吗?”老陈煞有其事地指着屏幕里的代码:

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

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

“当然是把 try-catch 说到外面啊!”老陈脑子都不转一下,信口开河。

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

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

扯什么 try-catch 性能问题?

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

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

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

public class TryCatchTest {
    @Benchmark
    public void tryfor(Blackhole blackhole) {
        try {
            for (int i = 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,跑的成果如下:

扯什么 try-catch 性能问题?
能够看到,两者的功能(数字越大越好)其实差不多:

  • fortry: 86,261(100359-14098) ~ 114,457(100359+14098)
  • tryfor: 95,961(103216-7255) ~ 110,471(103216+7255)

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

扯什么 try-catch 性能问题?
老陈一看傻了:“说好的功能影响呢?怎样没了?”

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

tryfor 的字节码

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

扯什么 try-catch 性能问题?

fortry 的字节码

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

扯什么 try-catch 性能问题?

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

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

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

扯什么 try-catch 性能问题?

而且还有下面一段话:

扯什么 try-catch 性能问题?

正所谓听话不能听一半,曾经读书时候最怕的就是一知半解,由于彻底理解选择题能选对,彻底不明白蒙或许蒙对,一知半解必定选到过错的选项!

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

扯什么 try-catch 性能问题?

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

扯什么 try-catch 性能问题?

这操作我只能说有点逆天,这两个完成的对比就有功能损耗了

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

扯什么 try-catch 性能问题?

成果如下:

扯什么 try-catch 性能问题?

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

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

  1. try-catch 相比较没 try-catch,的确有一定的功能影响,可是旨在不引荐咱们用 try-catch 来替代正常能不必 try-catch 的完成,而不是不让用 try-catch
  2. for循环内用 try-catch 和用 try-catch 包裹整个 for 循环功能差不多,可是其实两者本质上是事务处理方式的不同,跟功能扯不上联系关键看你的事务流程处理。
  3. 尽管知道try-catch会有功能影响,可是事务上不需求避忌其运用,事务完成优先(只需不是书中举例的那种逆天代码就行),非特殊情况下功能都是其次,有意识地避免大规模的try-catch,只 catch 需求的部分即可(没把握全 catch 也行,代码安全履行榜首)。

“好了,老陈你懂了没?”

“行啊yes,BB是一套一套的,走请你喝燕麦拿铁!” 老陈一把拉起我,我直接一个挣脱,“少来,我刚喝过咖啡,你那个倒竖洗头,赶紧的!”我立马意识到老陈想岔开话题。

“洗洗洗,咱们先喝个咖啡,晚上回去给你洗!”

晚上22点,老陈发来一张图片:

扯什么 try-catch 性能问题?

你别说,这头发至少比三毛多。

我是yes,咱们下篇见~