Tomcat

您所在的位置:网站首页 tomcat加载war包缓慢 Tomcat

Tomcat

2023-08-01 11:16| 来源: 网络整理| 查看: 265

 

 

问题描述

最近在升级Tomcat,我们有两个绝对相同的服务器(硬件和操作系统)。两者都运行Jdk_1.8.0_191,一台安装了 tomcat_7.x,一台安装了 tomcat_8.5.60。

启动和VM参数以及特定于应用程序的设置完全相同。唯一的区别是IP地址,当然还有主机名。

下面情况都是相同war包相同Tomcat情况下:

系统Tomcat版本能否启动 Windows Tomcat7 能 Windows Tomcat8 能 Linux Tomcat7 能 Linux Tomcat8 不能

 

Tomcat7加载Jar包原理

Tomcat自己实现了自己的类加载器,用于加载自己本地项目中jar包中的所有class文件,所以在相同的类加载器下,

如果有相同路径名和类名那么加载顺序就是根据jar包的顺序来决定的。谁的jar包先进来,那么就先加载哪个类。

但是为什么在Tomcat7所有环境都能运行正常,而在Tomcat8中就不行了呢? 于是就查看了Tomcat7的源码在Context加载项目中的jar包时

Tomcat7加载jar部分,在WebappLoader.setRepositories()方法中,粘贴出其中重要代码。

// Looking up directory /WEB-INF/lib in the context NamingEnumeration enumeration = null; try { //这一句是获得jar包的路径 enumeration = libDir.list(""); } catch (NamingException e) { IOException ioe = new IOException(sm.getString( "webappLoader.namingFailure", libPath)); ioe.initCause(e); throw ioe; }

list是获得了应用中WEB-INF下lib下所有jar包的路径。我们跟踪进去发现FileDirContext 的list方法中有下面这一句:

Arrays.sort(names); // Sort alphabetically

我们可以发现在Tomcat7中对获得所有jar包作了一个排序的动作。对jar包进行了首字母a-z进行了排序。

而我们所期望加载的那个jar包首字母正好在错误jar包的前面。

 

Tomcat8加载Jar包原理

上面我们知道了为什么在所有项目中Tomcat7能启动起来的原因了,是因为Tomcat7做了排序的动作,那么在Tomcat8加载Jar包时,又是怎么做的呢?

Tomcat8在加载源码的时候是通过StandardRoot.processWebInfLib()方法进行加载的

protected void processWebInfLib() throws LifecycleException { WebResource[] possibleJars = listResources("/WEB-INF/lib", false); for (WebResource possibleJar : possibleJars) { if (possibleJar.isFile() && possibleJar.getName().endsWith(".jar")) { createWebResourceSet(ResourceSetType.CLASSES_JAR, "/WEB-INF/classes", possibleJar.getURL(), "/"); } } }

在这我们可以看到Tomcat没有对取出来的Jar作任何动作,仅仅是File file = new File()这样遍历出来了。

那么为什么相同的Tomcat8相同的War包在Windos能启动起来,但是在Linux中都启动不起来呢?

经过试验发现Java的获取文件夹下面的所有文件是跟操作系统的文件系统有关系的,相同的文件夹内容,在Windows中取出来,输出名字你会发现输出是经过a-z排序过的,

但是在Linux中你可以根据命令ll -fi就可以输出自然顺序,你会发现没有什么规律可言。

 

解决

到这里上面描述的所有问题我们都能解释通了,接下来就该如何解决了。

修改Tomcat8的源码,在获取所有Jar包的时候,也对它进行排序 解决掉有冲突的文件,使用统一的版本。以下命令可以找到重复的jar包引用: mvn dependency:tree -Dverbose -Dincludes=io.netty

第一种解决办法只能解决一时问题,即项目能正常启动起来,但是一旦随后涉及到了相关类的修改,那么冲突类的哪个类呢?那么这个问题肯定是一个定时炸弹。

第二种方案是找到有冲突的文件,然后找出不用的那个给删除掉,但是发现删除一个又会蹦出其他的,删除了好几个以后发现由于买的项目代码不规范,

所以这种现象特别多,如果单纯靠手工筛选的话极其麻烦。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3