重载Throwable.fillInStackTrace方法已提高Java性能这样的做法对法?

重载Throwable.fillInStackTrace方法已提高Java性能这样的做法对法?

总有哪么些人拿Java异常的性能问题说事,做法是为自定义异常重载Throwable.fillInStackTrace方法,让其返回this。这样做,在测试时确实会快很多,但有什么不妥的地方吗?
关注者
41
被浏览
3022
5 个回答

只要那个自定义异常类型是真的不需要stack trace的,我也会推荐覆写fillInStackTrace()为直接返回this。
爬栈是抛异常开销大的主要原因之一。

<- 但注意好前提就是了——要确定真的肯定绝对不需要stack trace的话。

一个简单的例子是,“滥用”异常来实现某些特殊控制流结构的场景,此时stack trace肯定是没用的,那个异常对象本身其实也没用,只有它的类型和抛出它带来的控制流跳转才有用,那就应该覆写fillInStackTrace()。

=======================================

然后从反面举个例子。HotSpot VM有个许多人觉得“匪夷所思”的优化,叫做fast throw:有些特定的隐式异常类型(NullPointerException、ArithmeticException( / 0)之类)如果在代码里某个特定位置被抛出过多次的话,HotSpot Server Compiler(C2)会透明的决定用fast throw来优化这个抛出异常的地方——直接抛出一个事先分配好的、类型匹配的异常对象。这个对象的message和stack trace都被清空。抛出这个异常的速度是非常快,不但不用额外分配内存,而且也不用爬栈;但反面就是可能正好是需要知道哪里出问题的时候看不到stack trace了。
从Sun JDK5开始要避免C2做这个优化还得额外传个VM参数:-XX:-OmitStackTraceInFastThrow。

覆写fillInStackTrace()为直接返回this就像是人肉做C2所做的那种优化…的一部分效果。反正肯定会有人抱怨这样不好的啦,是不是要顶住压力硬上就看到底在特定场景里带来的性能好处是不是真的那么重要了。
可以。但是最主要的是取决于你怎么使用Exception。
有种观点认为,业务失败异常流程应该基于Exception控制,在这样的项目里就会看到大量的基于业务定义的Exception类,比如UserNotFoundException,LoginFailException什么的。或者把Service层所有的异常分支都包装成一个ServiceException什么的。这种情况下,throw Exception 就成为一个很常见的事件,这时重载fillInStackTrace 是可以有效益的。
但是我看到的大多数情况,大家还是把Exception作为技术上的异常而不是业务上的异常。所以,理论上要用到异常的时候不多。要真是发生了Exception,由于超出预期,反而恰恰需要stack trace。
JDK7开始已经原生支持爬栈开关
重载fillInStackTrace在业务异常中很常见,但是如果一定要说弊端的话,如果想要stack的时候反而没有办法了,屏蔽异常栈主要是为了不执行private native Throwable fillInStackTrace(int dummy);这个方法而提高效率,出于这个目的考虑的话有更好的方案,动态决定需不需要异常栈——新增业务异常增加构造函数,用参数决定是否需要异常栈。调用Throwable的构造函数:
protected Throwable(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace);
参数writableStackTrace直接可以决定需不需要执行fillInStackTrace来提高性能。
如果楼主做的是业务系统的话,建议避免使用这种做法来提高性能,从其他方面考虑吧。像R大说的,不需要stacktrace信息的时候,可以覆盖这个方法达到提高异常性能的目的。不过,业务系统变化太快,今天不需要异常信息,说不定明天就需要了。我自己就遇见过这样的case。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值