背景

之前做的小工具一个jsqlparse+git做的小工具帮我节省时间摸鱼昨天突然停止工作,看了下jvm并没有退出,但是看日志确实有不少Error输出,虽说是一个普通的NPE,但是分析了一下却疑点重重,所以花点时间来一探究竟,最终又掌握一个jvm知识点,还是比较有意思。

错误现场

以下是示例代码,为了说明问题做了简化,大概意思是使用CCJSqlParserUtil去解析一段sql语句,如果解析出错了以后从JSQLParserException.getMessage()中利用正则提取出具体的行和列。

Statements statements = null;
Set<Integer> sqlSet = new HashSet<>();
String sql ="alter table test add column varchra(4)";
try {
statements = CCJSqlParserUtil.parseStatements(sql);
} catch (JSQLParserException e) {
Pattern pattern = Pattern.compile("line (\\d+), column (\\d+)");
String message = e.getMessage();
Matcher m = pattern.matcher(message);
int line = -1;
int column = -1;
while(m.find()){
int groupCount = m.groupCount();
if(groupCount > 0){
line = Integer.parseInt(m.group(1));
column = Integer.parseInt(m.group(2));
break;
}
}
}

上面那个错误sql解析出错了以后的异常信息如下:

Encountered unexpected token: "varchra" <S_IDENTIFIER>
at line 1, column 29. Was expecting: "COMMENT"

那个诡异的NPE 栈如下:

java.lang.NullPointerException: null
at java.util.regex.Matcher.getTextLength(Matcher.java:1283)
at java.util.regex.Matcher.reset(Matcher.java:309)
at java.util.regex.Matcher.<init>(Matcher.java:229)
at java.util.regex.Pattern.matcher(Pattern.java:1093)
at xxx.ScriptUtil.sqlParse(ScriptUtil.java:41)

很显然是e.getMessage()返回了null导致pattern.matcher(message)失败,但是e.getMessage()理论上来讲不会是null,有点玄学的味道,一般解决玄学的首要方法是重启大法(个人观点,欢迎来喷,哈哈)。果然,重启了以后竟然好了,好奇心一下就被激发了。

错误原因

网上一通搜索确实类似的案例不少,大概的意思是jvm对异常处理这块做了优化,如果频繁抛出某种异常jvm会对这些异常做一些处理,使用JVM初始化的时候创建的那些异常对象来替代本应该新建的异常对象,因此这些异常栈和Message是空的,这一特性受OmitStackTraceInFastThrow参数的管控,可以通过-XX:+OmitStackTraceInFastThrow开启,或者-XX:-OmitStackTraceInFastThrow关闭,看完确实恍然大悟,但是并没有找到官方的一些说明,还是心有不甘,决定在openjdk源码中找找答案,全局在openjdk8的源码中搜索OmitStackTraceInFastThrow关键字,确实得到了想要的答案,一起来看下。

结合网上的一些结论和源码来看只有以下几类异常才会触发OmitStackTraceInFastThrow,分别是NullPointerException、ArithmeticException、ArrayIndexOutOfBoundsException、ArrayStoreException、ClassCastException,最终发现是有一个脚本文件的内容为空,会触发jsqlparse发生ArrayIndexOutOfBoundsException,进而触发了OmitStackTraceInFastThrow特性,导致工具代码中e.getMessage()返回null而触发NPE造成工具停止运行的假象。

修复办法

  1. 使用-XX:-OmitStackTraceInFastThrow关闭这一特性;

  2. 对执行逻辑优化,如果发现脚本文件内容为空就直接返回,不再继续执行;

推荐阅读

https://opts.console.heapdump.cn/result/query/Ex13k

https://heapdump.cn/topic/OmitStackTraceInFastThrow

一个jsqlparse+git做的小工具帮我节省时间摸鱼

  

  

  

案例分享-Exception.getMessage突然为null的更多相关文章

  1. ArcGIS Add-in插件开发从0到1及实际案例分享

    同学做毕设,要求我帮着写个ArcGIS插件,实现功能为:遍历所有图斑,提取相邻图斑的公共边长及其他属性(包括相邻图斑的ID),链接到属性表中.搞定后在这里做个记录.本文分两大部分: ArcGIS插件开 ...

  2. 性能调优案例分享:jvm crash的原因 1

    性能调优案例分享:jvm crash的原因   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq: ...

  3. 前端案例分享(一):CSS+JS实现流星雨动画

    目录 引言 1.效果图 2.源码 3.案例解析 4.小问题 5.结语 引言        平常会做一些有意思的小案例练手,通常都会发到codepen上,但是codepen不能写分析.        所 ...

  4. Elasticsearch Sliced Scroll分页检索案例分享

    面试:你懂什么是分布式系统吗?Redis分布式锁都不会?>>>   The best elasticsearch highlevel java rest api-----bboss ...

  5. 【案例分享】在 React 框架中使用 SpreadJS 纯前端表格控件

    [案例分享]在 React 框架中使用 SpreadJS 纯前端表格控件 本期葡萄城公开课,将由国电联合动力技术有限公司,资深前端开发工程师——李林慧女士,与大家在线分享“在 React 框架中使用 ...

  6. Office 2010 KMS激活原理和案例分享

    Office 2010 KMS激活原理和案例分享     为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企业客户推出了新的批量激活方式:KMS和MAK.这 ...

  7. Office 2010 KMS激活原理和案例分享 - Your Office Solution Here - Site Home - TechNet Blogs

    [作者:葛伟华.张玉工程师 ,  Office/Project支持团队, 微软亚太区全球技术支持中心 ] 为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企 ...

  8. 老李案例分享:Weblogic性能优化案例

    老李案例分享:Weblogic性能优化案例 POPTEST的测试技术交流qq群:450192312 网站应用首页大小在130K左右,在之前的测试过程中,其百用户并发的平均响应能力在6.5秒,性能优化后 ...

  9. 性能调优案例分享:Mysql的cpu过高

    性能调优案例分享:Mysql的cpu过高   问题:一个系统,Mysql数据库,数据量变大之后.mysql的cpu占用率很高,一个测试端访问服务器时mysql的cpu占用率为15% ,6个测试端连服务 ...

  10. 老李案例分享:MAT分析应用程序服务出现内存溢出过程

    老李案例分享:MAT分析应用程序服务出现内存溢出过程   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loa ...

随机推荐

  1. 如何在没有第三方.NET库源码的情况,调试第三库代码?

    大家好,我是沙漠尽头的狼. 本方首发于Dotnet9,介绍使用dnSpy调试第三方.NET库源码,行文目录: 安装dnSpy 编写示例程序 调试示例程序 调试.NET库原生方法 总结 1. 安装dnS ...

  2. Java笔记(细碎小知识点)1

    1.Dos命令:dir:打出当前目录结构:md:创建文件夹:cd+文件夹地址:跳转到当前目录下的对应文件夹:cd..:跳转到上一目录:rd+文件夹:删除文件夹中东西:del+文件(或 "*. ...

  3. Springboot项目使用Undertow替换内置Tomcat服务器,实现RESTFUL接口web应用

    Maven实例:pom.xml文件中添加更换依赖 <dependency> <groupId>org.springframework.boot</groupId> ...

  4. ⭐volatile⭐ 用volatile关键字则会从内存中直接读取变量的值

  5. Python基础——深浅拷贝、python内存泄露、你并不了解的format、decimal

    文章目录 深浅拷贝 先看赋值运算 浅拷贝copy 深拷贝deepcopy 相关面试题 python内存泄露 起因 方案 编写安全的代码 弱引用 你并不了解的format.decimal format格 ...

  6. Go 语言的前生今世与介绍

    Go 语言的前生今世与介绍 目录 Go 语言的前生今世与介绍 一. Go 语言的发展 1.1 Go 语言是如何诞生的? 1.2 Go语言的早期团队和演进历程 1.3 Go语言正式发布并开源 1.4 G ...

  7. CUDA C编程权威指南:2.1-CUDA编程模型

      本文主要通过例子介绍了CUDA异构编程模型,需要说明的是Grid.Block和Thread都是逻辑结构,不是物理结构.实现例子代码参考文献[2],只需要把相应章节对应的CMakeLists.txt ...

  8. pta2023年9月7日 第五期

    5月23日   11月14日   有效期3年: 更新方式待定:  双方认证合作CCF编程培训师资认证(PTA)中国计算机学会https://pta.ccf.org.cn/中国科教工作者协会(原:中国青 ...

  9. 手敲,Ascend算子开发入门笔记分享

    本文分享自华为云社区<Ascend算子开发入门笔记>,作者: JeffDing . 基础概念 什么是Ascend C Ascend C是CANN针对算子开发场景推出的编程语言,原生支持C和 ...

  10. 轻松掌握组件启动之MongoDB(下):高可用复制集架构环境搭建

    引言 上一章节中,我们详细介绍了在典型的三节点复制集环境中搭建MongoDB的步骤和注意事项.从准备配置文件到启动MongoDB进程,我们一步步指导读者完成了环境的设置.在本章节中,我们将进一步深入, ...