OpenJDK 8环境下无栈轨迹NullPointerException解决方案咨询
问题解答
你当前使用的OpenJDK 64-Bit Server VM属于HotSpot架构虚拟机,和Oracle HotSpot JVM的核心运行时逻辑完全一致,-XX:-OmitStackTraceInFastThrow参数完全可以解决你遇到的隐式异常无堆栈问题。
原理说明
HotSpot虚拟机默认开启了一项性能优化:当代码中同一位置反复抛出某类内置隐式异常(包括空指针异常NPE、数组下标越界异常、类转换异常、算术异常等)的次数达到内部阈值后,虚拟机会直接复用预先生成的、不带堆栈轨迹的异常实例,跳过异常构造时的栈信息采集流程,以此减少性能开销。
这个优化并非Oracle HotSpot独有,OpenJDK HotSpot从Java 5版本开始就已内置该特性,你使用的Java 8版本OpenJDK默认配置为-XX:+OmitStackTraceInFastThrow(即开启栈信息省略优化),添加-XX:-OmitStackTraceInFastThrow参数即可关闭该优化,让所有异常都正常携带完整堆栈轨迹。
参数配置方法
根据你的项目部署方式不同,参数添加位置如下:
- 直接命令行启动Jar包:在
java启动指令后、Jar包路径前添加参数即可,示例:
java -XX:-OmitStackTraceInFastThrow -jar your-project.jar
- Tomcat容器部署:
- Linux环境:修改Tomcat目录下
bin/catalina.sh文件,在文件开头位置追加JAVA_OPTS="$JAVA_OPTS -XX:-OmitStackTraceInFastThrow" - Windows环境:修改Tomcat目录下
bin/catalina.bat文件,在文件开头位置追加set JAVA_OPTS=%JAVA_OPTS% -XX:-OmitStackTraceInFastThrow
- Linux环境:修改Tomcat目录下
- IDEA本地启动调试:打开对应启动项的
Run/Debug Configurations面板,在VM options输入框中填入-XX:-OmitStackTraceInFastThrow,保存后重启服务即可 - Systemd托管服务启动:编辑对应服务的
.service配置文件,在ExecStart字段的java启动命令中追加该参数,执行systemctl daemon-reload后重启服务生效
注意事项
- 关闭该优化会带来极少量的性能开销,绝大多数业务场景下该开销可完全忽略,不会影响服务正常运行
- 你当前使用的slf4j日志记录写法
logger.error("ERROR in while processing data", e)是正确的,需保持异常对象e直接作为第二个参数传入,不要只传入e.getMessage(),否则即使异常携带堆栈也无法被日志框架打印
内容的提问来源于stack exchange,提问作者Rohit Dakota
相关产品推荐
相关产品推荐

