写点什么

JVM 对空指针的优化

作者:陈德伟
  • 2025-08-28
    浙江
  • 本文字数:1483 字

    阅读完需:约 5 分钟

现象

  • 线上有业务出现了空指针,但让人奇怪的是只是打印了 java.lang.NullPointerException ,而没有打印对应的调用堆栈信息,这让我们无法知道这个空指针到底是哪一行代码产生的:


java.lang.NullPointerExceptionjava.lang.NullPointerExceptionjava.lang.NullPointerExceptionjava.lang.NullPointerExceptionjava.lang.NullPointerExceptionjava.lang.NullPointerException
复制代码

原因

  • 通过网上搜索,发现是 HotSpot JVM 对异常的一个优化,要理解为什么做这个优化,就得了解 JVM 是如何处理异常的

  • JVM 处理异常的流程

  • 当程序抛出一个异常时,JVM 会创建一个对应的 Exception 对象,这个对象里会保存一份调用堆栈的快照

  • 然后 JVM 会从异常发生处开始,顺着堆栈一直往上找,直到找到了一个异常处理代码,通常来说就是 catch 语句

  • 找到异常处理代码后,JVM 会进行类型匹配,看看 catch 的类型和抛出的异常类型是否匹配,匹配就由此处语句处理,不匹配则继续往上找。这就是俗称的爬栈

  • 如果还找不到处理语句,异常会一直往上抛,直到 JVM 里的运行时系统,然后 JVM 回查抛出异常所在的线程和线程组是否设置了 UncaughtExceptionHandler ,没有就自己处理了

  • 从上面流程可以看出,处理异常时 JVM 除了要分配内存创建新对象外,还要爬栈做类型匹配。而为了保证异常堆栈的准确性,每次抛出时异常对象都必须是新建的,如果抛出大量异常还是挺费资源的,所以一般不推荐滥用异常实现流程控制

  • 而对于一些特定的隐式异常,比如 NullPointerExceptionArithmeticException 之类的,如果在同一个地方频繁抛出,HotSpot 的 C2 编译器会自行就决定使用一个叫 fast throw 的技术来进行优化这个异常抛出的流程

  • fast throw 技术

  • 对于一些频繁抛出的特定异常,HotSpot 会直接抛出一个预先定义好的、类型匹配的异常对象

  • 这个对象的 StackTrace、message 都直接被设置成了空,因此不需要每次抛出都要新建对象,也不需要爬栈。速度非常快,也节省资源

  • 但因为堆栈被清空,所以我们只知道异常名,和捕获异常的代码行,不知道异常调用链,连异常发生在代码哪一行也不知道

解决方案

  • fast throw 优化是默认开启的,如果想要关闭,需要在启动参数里添加 -XX:-OmitStackTraceInFastThrow

关联思考

  • Java 中的异常

  • try 块里内容应该尽量少,只包含实际抛异常的内容即可。就像本次,由于 try 里的内容过多,导致无法通过猜测定位问题,只能重启服务

  • 检查型异常使用场景很狭隘,不要随便使用。检查型异常向上抛,是为了让调用者自己灵活处理。想法很好,但实际上大部分检查型异常调用者都处理不了,只能接着往上抛,然后最外层统一包一下。即使处理,也基本上就打个错误日志,然后 return ,这就失去了检查型异常的初衷。现在 Spring 等框架代码基本不会抛检查型异常

  • 静态异常对象

  • 异常有个特殊地方就是:一定要在发生时创建,才能包含正确的调用栈,在 java.lang.Throwable 的文档里也有强调

  • 以前好像有见过做优化,然后把异常对象设置为静态,导致了堆栈固化,从而无法查找问题的案例

  • java.lang.Throwable JavaDoc:

  • Typically, these instances are freshly created in the context of the exceptional situation so as to include relevant information (such as stack trace data).

参考资料

发布于: 刚刚阅读数: 2
用户头像

陈德伟

关注

还未添加个人签名 2018-04-26 加入

兴趣广而不精,从小爱玩游戏还是个手残,爱看书这么多年还是拙于下笔。从事软件行业十几年也没有什么拿的出手的成就,只能安慰自己贵在坚持。译有《On Java》、《Java程序员修炼之道》《Spring Boot实践》等书。

评论

发布
暂无评论
JVM对空指针的优化_Java_陈德伟_InfoQ写作社区