jar冲突问题与Tomcat 加载jar的顺序

前言

笔者在解决业务问题的时候,很多业务提出了为啥我的服务在测试环境啥问题都没有,发布生产就出问题了,第一反应是配置不一样?实际上部分原因可能还与发布的容器有关,比如Tomcat8,比如jar冲突。刚好解决了jar冲突的事情,总结分析原因。

1. tomcat源码下载

Tomcat的新版本是可以直接下载源码的,但是Tomcat7就只能

jar冲突问题与Tomcat 加载jar的顺序_第1张图片

Index of /dist/tomcat (apache.org)

记得下载src

jar冲突问题与Tomcat 加载jar的顺序_第2张图片

2. tomcat 7与tomcat 8的区别

以非嵌入式tomcat 7 8 为例

2.1 Tomcat7

tomcat加载WEB-INF/lib是在org.apache.catalina.loader.WebappLoader加载的

jar冲突问题与Tomcat 加载jar的顺序_第3张图片

 可以看到加载是通过

DirContext

实现的,这个在tomcat有2种方式WAR、File

jar冲突问题与Tomcat 加载jar的顺序_第4张图片

Tomcat通过解压运行,加载默认通过File,会把lib下得jar按照字母排序,加载jar的顺序固定,所有环境一样,要么都冲突,要么都正常,环境验证好就不存在类冲突问题。

2.2 tomcat 8

 tomcat8的设计有些不同,代码重构了,在org.apache.catalina.loader.WebappClassLoaderBase下的start

jar冲突问题与Tomcat 加载jar的顺序_第5张图片

 

可以看到

jar冲突问题与Tomcat 加载jar的顺序_第6张图片

 进一步继续,直接file.list获取过滤jar,并没有排序

jar冲突问题与Tomcat 加载jar的顺序_第7张图片

 以macOS为例

jar冲突问题与Tomcat 加载jar的顺序_第8张图片

 直接查看jdk源码

jar冲突问题与Tomcat 加载jar的顺序_第9张图片

初步看扫描的代码,大致是顺序与服务器的信息有关,导致Tomcat8在不同服务器WEB-INF/lib的jar的顺序不一样,加载的类如果有冲突会不一样。 

3. 为什么相同的war,不同机器有的冲突有的没有

实际上Tomcat7是不存在问题的,Tomcat8就会出现类冲突的情况,本质还是Tomcat8暴露了类冲突的情况,并不是Tomcat7解决问题,而是隐藏了问题。

解决类冲突还是需要静态扫描,人工比对处理(排jar),扫描也很好写,包与类路径一样即为可能冲突类

spring boot又是怎么处理的呢,通过jarFile的迭代器迭代的,所以是顺序的,并且jar启动的的jar的BOOT-INF/lib也是不会顺序变换的

jar冲突问题与Tomcat 加载jar的顺序_第10张图片

总结

仅仅是Tomcat使用读取文件的方式启动就会根不同机器的环境相关,顺序不一致而出现类冲突的暴露问题,说明了不同环境问题出现的原因也会跟执行容器相关。这可能也是spring boot发展的一个原因。当然Tomcat也可以war读取,不解压运行,就不会有这个问题了,只是不知道什么原因不常用。

你可能感兴趣的:(linux,server,Java,架构设计,tomcat,jar,java)