异常表现
项目本地开发环境启动正常, 部署到生产环境启动卡死.
解决步骤
- 首先当然是找到启动日志. 由于项目在windows Server 2012上运行, 注册为windows服务. 所以不会有控制台日志, 所有日志均需要在日志文件夹中找到. 最终发现无限循环输出日志:
Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter.
Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter.
Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter.
Logging initialized using ‘class org.apache.ibatis.logging.stdout.StdOutImpl’ adapter.
… …
- 到网上查找解决办法, 都说是Mybatis的Mapper文件解析出错导致, 但是反复检查Mapper文件, 并与上一版本项目部署时的代码进行核对, 并没有发现错误.
- 找到了这篇文章:https://blog.csdn.net/isea533/article/details/51277786, 授人以鱼不如授人以渔, 这里面并没有直接告诉说是什么引起的异常. 而是通过断点调试的方式来找到异常.
- 但是由于本地启动正常, 无法进行本地调试, 百度发现Eclipse居然可以远程调试!https://blog.csdn.net/guolong1983811/article/details/78081470
- 经过远程调试, 最终找到异常, 是由于新增的一个jar包是通过jdk1.8打包的. 而整个项目的环境一直运行在jdk1.7环境下, 最终导致上面的一系列问题.
详细解决过程
查看Tomcat日志文件
如图为一次启动生成的日志:
https://www.cnblogs.com/qlqwjy/p/8036091.html解释了各个文件的含义:
- catalina.日期.log – 这个主要是记录tomcat启动时候的信息,类似于我们在eclipse中启动服务的时候在控制台看到的信息。在里面可以看到启动的JVM参数以及操作系统等日志信息。如果没有使用log4j等日志机制,系统的的错误信息与打印语句也在这个日志文件中记录。(linux下所有的日志都在catalina.out中)
- commons-daemon.日期.log – 这个日期放的估计是利用服务方式启动tomcat作为守护进程的日志记录,因为我的tomcat启动方式是以服务的方式启动的,索引产生这个日志文件记录了服务的启动状态。
- host-manager.日期.log – 这个估计是放tomcat的自带的manager项目的日志信息的,也没有看到有什么重要的日志信息.
- localhost.日期.log – 这个类似于第一种日志,可是信息没有第一种全
- localhost_access_log.日期.txt – 这个是存放访问tomcat的请求的所有地址以及请求的路径、时间,请求协议以及返回码等信息(重要)
- manager.日志.log – 这个估计也是manager项目专有的日志文件,看不出有什么重要的信息
- tomcat7-stderr.日期.log – 这个是log4j的错误日志,因此在程序中要合理的捕捉异常。
- tomcat7-stdout.日期.log(类似于eclipse的控制台的信息) – 这个是程序中的System语句打印的日志(包括系统抛出的异常),也终于明白了为什么一再强调不能用打印语句进行系统调试
最后在tomcat7-stdout.2018-10-11.log中找到了问题:
远程断点调试
- 配置服务器的tomcat开启远程断点调试监听:
SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8081,server=y,suspend=n
- Eclipse连接远程服务器:
- 根据网上查找到的断点位置, 在图上位置加上断点:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory的protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs)方法
org.springframework.beans.factory.support.AbstractBeanFactory的protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) 方法
- 使用startup.bat启动远程服务.
- 启动Eclipse远程调试.
- 结果上面第一个断点处一直进入, 第二个断点没有反应. 我把第一个断点关掉. 过了一会, 进入第二个断点.
终于得到错误日志了: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sqlSessionFactory’ defined in class path resource [mapper/applicationContext-db.xml]: Invocation of init method failed; nested exception is java.lang.UnsupportedClassVersionError: com/frog/report/model/DataSource : Unsupported major.minor version 52.0 (unable to load class com.frog.report.model.DataSource)
同时发现每打印一句之前循环输出的日志, 就进入断点一次.
根据上面的错误日志, 可以知道version52.0对应的是jdk1.8, 而我们的项目使用的是jdk1.7, 所以出错.
问题总结
引起这个问题有两方面原因:
- 开发环境管理混乱, 没有使用统一的jdk版本进行控制.
- 项目的日志管理存在问题. 下图中实际上是应该输出错误日志的, 这样就会更好的解决问题.
最后发现log4j与logback冲突导致日志输出出现问题, 错误日志没有输出出来: