最近线上项目的关键环节突然抛出了一个数据库访问的空指针异常,不免神经一紧,经过最终排查,确认了该问题属于mybatis 3.3.0(不包含)以下版本已存在的bug,新版本的mybatis已经修复,具体情况如下:
系统jar版本

异常堆栈

排查过程

  1. 根据堆栈信息,初步确定是mybatis的解析执行异常,通过搜索引擎进一步查证,该问题属于mybatis低版本中存在的并发bug,问题发生时也确实存在多个线程并发访问同一sql

    需进一步确认具体原因。
  2. 由于之前对mybatis执行过程中mapper文件中定义的mappedStatement的sql语句的解析构建及参数绑定了解不够充分,故结合日志中的异常sql语句,在dev环境进行模拟,熟悉执行流程:

项目启动阶段进行mapper文件的解析,构建XML的结构化对象

org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode解析statement, 并将结果维护在org.apache.ibatis.session.Configuration 的statementMap<statementId, statement>中,用于sql执行时依据statementId获取对应的statement

org.apache.ibatis.mapping.MappedStatement 结构,包含参数类型,结果类型,sql解析后的对象


org.apache.ibatis.scripting.xmltags.XMLScriptBuilder#parseScriptNode 解析sqlSource

  • sql执行解析阶段,根据statementId及参数选择相应的statement进行解析执行
    执行堆栈如下


    org.apache.ibatis.session.Configuration#getMappedStatement(java.lang.String, boolean) 执行时获取对应的statement对象


    根据statement中sqlSource对象及参数信息,对sql语句进行解析构建

    org.apache.ibatis.scripting.xmltags.MixedSqlNode#apply 解析where语句时(在此过程中出现的问题)


    org.apache.ibatis.scripting.xmltags.IfSqlNode#apply 解析if语句

    org.apache.ibatis.scripting.xmltags.ExpressionEvaluator#evaluateBoolean 通过ognl来解析表达式,如不等,大于等等

org.apache.ibatis.scripting.xmltags.OgnlCache#getValue 通过OgnlParser解析表达式(” settleDate != null”), 相同的表达式OgnlParser会单独创建一个,并对结果进行缓存,故此处无并发问题

org.apache.ibatis.ognl.SimpleNode#getValue ognl获取值的处理

org.apache.ibatis.ognl.SimpleNode#evaluateGetValueBody 当前表达式解析过程中,表达式” settleDate”属于ASTConst类型,且多线程并发执行解析该表达式时,共用同一个OgnlParser解析的结果,故下图部分可能存在并发问题,导致其中某个线程获取到的contantValue为null


Mybatis 3.3.0版本已对此处进行修改,解决了此处问题如下:


同时,通过堆栈溯源导致NPE是由于获取property(即String类型”settleDate”)值为空导致 org.apache.ibatis.ognl.ASTProperty#getValueBody

org.apache.ibatis.ognl.ASTNotEq#getValueBody 执行到此处不等式,解析完毕

  • 执行查询阶段
    org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler) 执行查询

    org.apache.ibatis.mapping.MappedStatement#getBoundSql 执行解析
  1. 通过上述步骤,及对OgnlParser等排除,最终确认并发的问题点

参考内容

Mybatis中问题记录

https://github.com/mybatis/mybatis-3/issues/224
https://issues.apache.org/jira/browse/OGNL-121

Mybatis各版本发布日志

https://github.com/mybatis/mybatis-3/releases
https://github.com/mybatis/mybatis-3/issues?q=milestone%3A3.3.0

Struts2.1.8 Ognl 漏洞浅析和解决方案

https://blog.csdn.net/xlxxcc/article/details/52244965

看到这里的小伙伴,如果你喜欢这篇文章的话,别忘了转发、收藏、留言互动!

最近我新整理了一些Java资料,包含个人精选的Java架构学习视频、大厂实战知识点、大厂内部面试题,如果你需要的话,欢迎私信我

如果对文章有任何问题,欢迎在留言区和我交流~

回想那天让我虎躯一震的bug:Mybatis Ognl引起的异常相关推荐

  1. 【CSS】虎躯一震!flex=1 和 flex-grow=1 竟然不一样!

    2019独角兽企业重金招聘Python工程师标准>>> 在以前做项目的时候,使用 flex,而且当遇到 子元素 需要 占满剩余空间 的时候,习惯性的会添加 flex=1 这个属性. ...

  2. 三行代码实现发布订阅,让面试官虎躯微微一震

    发布订阅模式: 定义对象间一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新 事件总线是对发布订阅模式的一种实现,也是一种集中式事件处理机制,允许不同组件之间相互 ...

  3. 公式之美:打通复杂思维的任督二脉

    公式之美打通复杂思维的任督二脉 >>>> 很多学生讨厌公式,其实并不是讨厌某这门学科. 很多时候,只是抗拒"背诵并应用"的死板考纲要求. 因为教学任务的繁重 ...

  4. OSChina 周三乱弹 —— 生活终于对我这只小猫咪动手啦

    2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单(2018)请戳(这里) [今日歌曲] @胖达panda  :分享有里知花的单曲<Yesterday on ...

  5. 动手学深度学习笔记3.4+3.5+3.6+3.7

    系列文章目录 动手学深度学习笔记系列: 动手学深度学习笔记3.1+3.2+3.3 文章目录 系列文章目录 前言 一.softmax回归 1.1 分类问题 1.2 网络架构 1.3 全连接层的参数开销 ...

  6. 错过一个订单后,吐槽下自己(顺便分享下书单),剧终版

    事先啰嗦几句 1. 纯叙述分享,分享一点创业过程的经历.也当挖坟自我重新认识(大概就是把以前的经历又翻出来的意思). 2. 前面叙述有"摇尾乞怜"之嫌,所以采用分段叙述的方式,只想 ...

  7. 团队的英文翻译缩写_团队英语怎么写

    暑假正是比赛季.从刚刚结束的第十五届"外研社杯"中小学生英语大赛(团体挑战赛)全国总决赛,传来好消息: 杭州高级中学表现非常亮眼.其中,贡院校区团队(胡乐阳.王祎宁.张璐瑶.领队老 ...

  8. 为什么我学51单片机很顺利,学STM32却一头雾水?

    五年懂行,十年称王. 当初自学转行的我,怎么也没想到自己能从事单片机开发10年. 王不敢称,还算懂行. 10年前我刚毕业,即将面临社会毒打,我慌得一批. 我学的是电气工程,后面主修电梯. 毕业后和大家 ...

  9. 奋斗吧,程序员——第四十七章 所谓伊人,在水一方

    一周后的球赛那天是个春光灿烂的日子,蔚蓝色的天空很蓝,球场上弥漫着一股荷尔蒙的味道. 对手是一家做电子商务的公司,这家公司招了好多刚毕业的大学生MM做客服. 所以球迷质量非常高,美女如云而且打扮时尚, ...

  10. python爬虫! 网站维护人员:真的求求你们了,不要再来爬取了,受不了了!!

    话说 在很久很久以前 小明不小心发现了一个叫做 学习python的正确姿势 从此一发不可收拾 看到什么网站都想爬取 有一天 小明发现了一个小黄网 里面的小姐姐 一个比一个诱人 看了一会这个小黄网 小明 ...

最新文章

  1. 编程入门:准备学Python入门编程 为什么前辈一直劝我不行?
  2. 对图片对比度和亮度的理解
  3. JUnit与TestNG:您应该选择哪种测试框架?
  4. mysql 文件系统规划_Mysql的文件系统规划以及日志配置
  5. Linux数据库1366错误,ERROR 1366 (HY000): Incorrect string value:’XXX’ for column 'XXX at row 1解决...
  6. Codeforces 374A - Inna and Pink Pony
  7. 8.总线设备驱动模型
  8. c语言笔试题7(25),嵌入式软件工程师C语言笔试题(7页)-原创力文档
  9. 基于Dijkstra算法和KM算法的网约车订单分配问题
  10. 实现Http Server的三种方法
  11. 詹森不等式到底是什么?
  12. 想知道程序员每天在干嘛吗?
  13. java8:lambda级联表达式(Cascading)或柯里化(Currying)原理简化详解
  14. Azuki:缔造NFT元宇宙品牌
  15. 安装Mozilla Firefox
  16. (极详细版)python绘制箱形图方法
  17. 手淘Android容器架构——Atlas的前世今生
  18. 【matlab矩阵运算】01、把矩阵展开成向量
  19. 机甲女战士如何上色?如何起稿和构图?
  20. Pygame游戏制作:配置pygame(必看)

热门文章

  1. 安卓版本与adb的问题
  2. db_LINK详解东子
  3. STM32 HAL库学习笔记-(SPI驱动ADXL345)
  4. 通过className属性给一个元素追加新class(addClass函数)
  5. 小功能⭐️Unity动态更改 Scripting Define Symbols (宏定义)
  6. excel 删除重复项_在Excel 2013列表中删除重复项
  7. 漏洞取证_使用Linux文件系统取证进行漏洞检测
  8. java将小写金额转为大写金额
  9. NAND Flash(spi nand flash和nand flash)和emmc以及ufs通过uboot烧写固件的一些差异
  10. UE4镜头抖动CameraShake