一个java空指针异常的解决过程
背景
上一篇讲了我们从另外一个部门迁移了一个线上系统回来,迁回来是为啥呢,因为这个好几年没新需求的系统,突然有新需求要开发,然后我就开发呗,其实就是在某个服务里加点表,然后提供个查询接口给app。这个服务用的架构是厂商的,不是servlet容器那一套,它技术还是很厉害,其实是c语言写了个reactor这种类似netty的通信框架,通信协议是私有的tcp协议,然后启动时还通过jni拉起了一个java虚拟机,通信框架就负责底层通信,并且像servlet那样来调用上层的java类中的service方法这样。
至于为啥厂商这么玩,我觉得无非是把底层这套通信框架打成二进制提供给我们,提高技术壁垒,防破解啥的,并且通过私有协议提升维护难度,这样的话,就可以一直收我们维护费了。这些就不过多吐槽了,反正好多服务就是这样被厂商绑死了。
在windows上,这个进程没法像tomcat这类容器一样运行起来,每次只能对java代码部分进行junit单元测试,只能在linux上才能运行起来。
像java代码部分,我们自己是用了spring那一套,就像下面这样,启动时直接new一个spring的ClassPathXmlApplicationContext,而下面的location就是application.xml这种spring配置文件的url。

由于厂商也提供了些自己的访问数据库的框架,之前这个服务就是用的厂商这套(类似于jdbcTemplate操作sql语句);我接手这个服务之后,感觉不太喜欢厂商那套,就还是引入mybatis的mapper这套,如下:

结果,我本地junit调试时好好的,丢到服务器上,直接运行不起来了。给我报了个空指针。

解决过程
各种怀疑
上面的图里,看着是mybatis在创建一个什么XPathFactory的时候报错了,然后上图又说解析什么mapper.xml失败了,我还在想,是文件路径没对吗,结果文件路径挺对的:

接下来,开始怀疑起了mybatis,由于接手的这个项目,素质不怎么样,各种jar包冲突啥的,大家看我下图就知道了,就上面报错的堆栈里的org.apache.ibatis.parsing.XPathParser这个类,我在项目里一搜,发现同名类有两个,为啥呢,因为下面第一个jar包是厂商的,它把mybatis的源码封进了自己的jar包里,且没改包名:

当然了,厂商那个jar包里不止这一个,拷贝了很多类进来,也不知道拷贝进来后改了些啥。
我这时候的想法是,看看到底加载的哪个class吧。
查看类加载情况
然后在jvm的启动参数加了打印类加载的jvm参数: -verbose:class

注意,这个是打印到console,或者对console进行重定向到文件。
我这边看了下,发现是对的,仔细检查了,没发现加载了厂商的jar包的类,看起来是对的:

看堆栈相关代码
然后开始在本地junit调试,结果没走到报错的地方。
看之前那个错误堆栈,报错就是在下面的jdk1.7中的XPathFactoryFinder类的220这一行:

然后,这个resource应该就是触发空指针的,如果说resource为null,那么217行这个迭代器就有问题,通过迭代器的next获取出来的值为null;而迭代器是在215行的createServiceFileIterator赋值的。

点进来后就傻了,有分支,不知道走了哪一条,好在天无绝人之路,此时,之前的-verbose:class参数起了作用:

通过这里分析,在加载完XPathFactoryFinder类后,不久就加载了javax.xml.xpath.XPathFactoryFinder.SingleIterator,那意思就是走了if那个分支。
但目前对怎么解决这个问题还是不清楚,无奈,先本地debug。
debug
虽然本地junit不能完全模拟linux服务器上的状况,但是先试试吧,结果,本地调试发现:
在之前那个分支处,本地windows时,classloader不是null:

那我是否怀疑了classloader的问题呢,怀疑的不多,因为以前本地调试tomcat的时候已经遇到过,本地debug时用的classloader和最终把war包丢到tomcat里运行时用的classloader那些,确实不一样。
在debug的过程中,对这个类的理解加深了一些,看起来,这个XPathFactoryFinder主要就是要获取到一个XPathFactory。

先是从property中查找,property为javax.xml.xpath.XPathFactory:http://java.sun.com/jaxp/xpath/dom,如果能找到对应的实现类,就用这个实现类去创建对应的XPathFactory,这块就和java中的SPI机制类似:

接下来呢,会尝试从配置文件获取C:\Program Files\Java\jdk1.7.0_80\jre\lib\jaxp.properties:

如果还是没有,才会走到我们报错的地方,即用spi机制,问题是我们因为classloader为null,走不到下图这里:

开启debug日志
在debug过程中,发现很多debug日志:

这个日志如何开启呢?

我们设置了下,如下:

这下,通过日志,我们更加明确了程序运行的轨迹。
设置property解决bug
接下来,就是怎么解决了,在debug过程中,我们发现,本地windows的话,默认最终的实现类就是com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl,其实就是jdk自带的:


那我们这里也就好说了,设置下property吧,解决问题就行了,至于为啥classloader为null,就没有继续深究了:

这次就运行正常了:

总结
bug记录下还是挺好,因为很快就忘了,后来要写上线变更文档,才想起来这么个事。
一个java空指针异常的解决过程的更多相关文章
- 一个Java程序的执行过程(转)
我们手工执行java程序是这样的: 1.在记事本中或者是UE的文本编辑器中,写好源程序: 2.使用javac命令把源程序编译成.class文件: 编译后的.class(类字节码)文件中会包含 ...
- 一个 java 文件的执行过程详解
平时我们都使用 idea.eclipse 等软件来编写代码,在编写完之后直接点击运行就可以启动程序了,那么这个过程是怎么样的? 总体过程 我们编写的 java 文件在由编译器编译后会生成对应的 cla ...
- 一个疑难bug的解决过程
一个crontab脚本,下载一个文件并把内容入mysql数据库.具体流程如下: 1, wget一个文件. 2,处理文件生成一个中间文件. 3,将中间文件load入库. 05 10 * * * /hom ...
- 记录一个前端bug的解决过程
人在江湖飘,哪能不挨刀. 我挨了重重一bug.严格来讲这可能是我职业生涯以来的首个悲惨经历,因为凭我的知识储备和经验,基本上任何可重现的bug都是可解的.然而这个bug却困扰了我三个月之久,它具有以下 ...
- java.lang.UnsatisfiedLinkError解决方法汇集(转载)
我的解决方法: 将sigar.jar拷贝到/WEB-INF/lib/下,但这个方法不知道是不是终极解决办法,暂时没问题,其他方法可参考下面. 运行JSP报表程序页面出现java.lang.Unsati ...
- 在Eclipse中,如何把一个java项目变成web项目
经常在eclipse中导入web项目时,出现转不了项目类型的问题,导入后就是一个java项目.解决步骤:1.进入项目目录,可看到.project文件,打开.2.找到<natures>... ...
- 深入理解Java对象的创建过程:类的初始化与实例化
摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...
- (转)深入理解Java对象的创建过程
参考来源:http://blog.csdn.net/justloveyou_/article/details/72466416 摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一 ...
- 深入学习Java对象创建的过程:类的初始化与实例化
在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类构造器完 ...
- 从解决一个java.lang.NoSuchMethodError想到的
今天在发布系统部署一个web app的时候,发现应用服务器(tomcat 7.0.26)不能正常启动,于是远程登陆到服务器上查看应用服务器的启动日志,在tomcat_home的logs/localho ...
随机推荐
- 使用搜索引擎时如何排除一些垃圾站点,比如csdn.net
使用搜索引擎时需要排除一些垃圾站点,比如csdn.net时,可以在关键词后面加上-site:csdn.net: stable diffusion docker部署TensorFlow 教程 -site ...
- AI Agent核心技术揭秘:从理论到实践(中篇)
认知是成本最低的对冲. --张三思维进化论 回顾与展望:从认知到技术的桥梁 在上一篇文章中,我们探讨了AI Agent的概念.特征和与传统AI的本质区别.我们认识到,AI Agent不仅是对话工具,更 ...
- 1K star!这个开源项目让短信集成简单到离谱,开发效率直接翻倍!
嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 "让简单的事情回归简单的本质" -- SMS4J 项目宣言 SMS4J ...
- 信息资源管理综合题之“S公司规划网络系统-内部用户需要使用的信息安全技术及其相应用途”
一.案例:S公司是某网络设备制造商在国内的一级代理商,总部设在上海,在外高桥有一处大型的仓库,其二级经销商客户分布在全国几十座大中城市,并在北京.成都.西安和沈阳等地设立了办事处.总部实施了ERP系统 ...
- 运筹学之"图解法求出最优解和最大利润"
11.某公司利用两种原料 A.B 生产甲.乙两种产品(吨),各产品所需的原料数,原料限量及单位产品所获利润如下表.企业目标是追求利润的最大化,试写出该线性规划问题的数学模型,并用图解法求出最优解和最大 ...
- Flutter适配HarmonyOS 5开发知识地图
还在为Flutter适配HarmonyOS 5头疼?这份知识地图,用实战解析+高频避坑指南,帮你快速打通跨平台开发任督二脉! ▌为什么这份资源值得你收藏? 分层进阶:从环境搭建→插件开发→性能优化,匹 ...
- 使用Vite创建一个动态网页的前端项目
1. 引言 虽然现在的前端更新换代的速度很快,IDE和工具一批批的换,但是我们始终要理解一点基本的程序构建的思维,这些环境和工具都是为了帮助我们更快的发布程序.笔者还记得以前写前端代码的时候,只使用文 ...
- odoo18运行报错问题解决
File "/Users/melon/.pyenv/versions/3.11.9/lib/python3.11/code.py", line 90, in runcode exe ...
- EasyExcel读取多个sheet表数据,自定义监听器
接口 /** * 导入 * * @param file * @return */ @PostMapping("/waitimport") public Result waitImp ...
- 阿里云javascript分片上传失败的解决办法
前端项目:React + Antd mobile + 阿里云OSS Node.js SDK实现文件上传. 在电脑上运行良好,放到手机上大文件就上传失败. 打开Chrome,地址栏输入`chrome:/ ...