目录
前言
最近开发的项目有个后台工具组件需要更新功能,但由于组件长期无改动,从主分支拉的代码居然无法启动。项目启动的过程中出现了一个之前从未遇到过的错误,本文主要记录了解决此问题的分析步骤与心路历程。
一、问题描述
背景:项目为spring框架写的web项目,启动使用的tomcat,启动过程中的主要报错信息如下:
ch.qos.logback.core.joran.spi.JoranException: I/O error occurred while parsing xml file
at ch.qos.logback.core.joran.event.SaxEventRecorder.handleError(SaxEventRecorder.java:76)
at ch.qos.logback.core.joran.event.SaxEventRecorder.recordEvents(SaxEventRecorder.java:64)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:134)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:99)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:76)
at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:68)
at com.github.diamond.client.PropertiesConfiguration.loadLogback(PropertiesConfiguration.java:482)
at com.xxx.edu.zx.machinetools.web.ServletContextConfigurationListener.contextInitialized(ServletContextConfigurationListener.java:30)
Caused by: org.apache.xerces.impl.io.MalformedByteSequenceException: Invalid byte 3 of 3-byte UTF-8 sequence.
at org.apache.xerces.impl.io.UTF8Reader.invalidByte(Unknown Source)
at org.apache.xerces.impl.io.UTF8Reader.read(Unknown Source)
at org.apache.xerces.impl.XMLEntityScanner.load(Unknown Source)
at org.apache.xerces.impl.XMLEntityScanner.skipString(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl.parse(Unknown Source)
at ch.qos.logback.core.joran.event.SaxEventRecorder.recordEvents(SaxEventRecorder.java:61)
... 53 more
二、分析过程
1、检查依赖冲突
看到第一句的时候,根据之前的经验,我自然想到了会不会是ch.qos.logback的jar包冲突导致的
ch.qos.logback.core.joran.spi.JoranException: I/O error occurred while parsing xml file
因此打开idea的查看pom依赖功能,发现排除冲突的jar包后,依旧无法启动。
2、网上搜索
而在搜索引擎中查找到的方法中。依次排查也没有找到问题的所在,例如
- 检查版本号是否正确,pom中ch.qos.logback的版本号均为1.1.3版本
- 删除本地maven仓库中的ch相关包,重新update项目下载
这时应该意识到排查此类问题还是不能够先入为主从网上搜索答案,还是需要回归代码
3、从代码角度排查
先找到报错的位置,从最顶层往下,找到这一句:
com.github.diamond.client.PropertiesConfiguration.PropertiesConfiguration.loadLogback(PropertiesConfiguration.java:482)
读取配置的代码报错,这个方法是启动的时候读取在线配置然后替换代码配置的。
接着往上找,报错的起始位置是:
PropertiesConfiguration.loadLogback("logback.xml");
那么基本确定为读取logback.xml文件错误。
接着找到报错的最终位置:
ch.qos.logback.core.joran.event.SaxEventRecorder.handleError(SaxEventRecorder.java:76)
try {
saxParser.parse(inputSource, this);
return saxEventList;
} catch (IOException ie) {
handleError("I/O error occurred while parsing xml file", ie);
}
接着找到报错信息中的关键信息:
org.apache.xerces.impl.io.MalformedByteSequenceException: Invalid byte 3 of 3-byte UTF-8 sequence.
at org.apache.xerces.impl.io.UTF8Reader.invalidByte(Unknown Source)
根据这句中的UTF8Reader报错,我恍然大悟,基本能确定是读取logback.xml的文件编码错误,导致项目启动失败。至此,原因已经找到,解决问题就简单多了。
三、解决方式
- 找到logback.xml文件通过txt或其他的工具查看,果然编码格式为带有BOM的UTF-8。
- 将文件只另存为UTF-8格式。
重新启动项目,终于能够启动成功了
总结
经过这次的排查问题,我意识到排查问题不能仅仅通过主观判断和网络搜索结果去排查,这种方法可能会瞎猫碰到死耗子解决问题,但是大多数情况还是不行的。
解决项目启动报错,不要因为害怕问题从没遇到过,直接摆烂,找人解决。至少要自己从代码层面去分析一遍,并结合网络上报错信息的搜索,大致做个判断,尽量做到自己搞定问题,这样才能提升自己分析问题的能力。