从lib目录加载jar文件的顺序

问题描述 投票:36回答:5

任何人都可以解释从Tomcat中的lib目录加载jar文件的顺序吗?它按字母顺序排列吗?随机?还是其他一些订单?

java tomcat classloader
5个回答
36
投票

这一切都在Tomcat's ClassLoading HOW-TO中描述。它不一定按字母顺序排列。如果您发现了这种行为,那么如果您打算让Web应用程序在服务器之间移植,则绝对不应该依赖它。例如,Tomcat 6“巧合地”命令它,但Tomcat 8没有。

总结一下,加载顺序如下:

  1. bootstrap / system(JRE/lib,然后server.loader
  2. webapp库(WEB-INF/classes,然后WEB-INF/lib
  3. 共同的图书馆(common.loader,然后Tomcat/lib
  4. webapp-shared libraries(shared.loader

如果您想保证在JAR Y之后加载JAR X,那么您需要将JAR X放在上面列表中稍后出现的其中一个位置。

然而,有一些例外,在tomcat docs中提到

最后,Web应用程序类加载器将始终首先委托JavaEE API类来执行Tomcat(Servlet,JSP,EL,WebSocket)实现的规范。 Tomcat中的所有其他类加载器都遵循通常的委托模式。

这意味着如果webapp包含任何JavaEE类(javax.*),那么tomcat将忽略它。

对于每个加载器,只要需要导入/执行并且尚未加载,JVM就会按顺序加载这些类。


32
投票

实际上,它是按字母顺序排列的! (在特定目录中,例如原始海报提到的'lib'目录。)

更具体地说,如果你查看Tomcat 6的源代码,在类FileDirContext中,方法list()会在找到的jar文件名数组上调用Arrays.sort()

我也手动测试了这个。我使用调用HelloWorld.getGreeting()的JSP创建了一个war,并将两个几乎相同的包含HelloWorld略有不同版本的jar放入WEB-INF / lib目录中。一个说“你好,世界”,另一个说“再见,残酷的世界”。

如果我将“Hello,world”版本命名为a.jar,并将“goodbye”版本命名为b.jar,并重新启动Tomcat,则会收到“Hello”文本。如果我用另一个方式命名罐子并重新启动Tomcat,我会得到“Goodbye”文本。

据我所知,此行为未记录,未指定,不应依赖。但它现在是按字母顺序排列的。


23
投票

在WEb-INF / lib文件夹中订购加载的jar。

对于tomcat 5-7,顺序是按字母顺序排列的。它使用排序。

对于tomcat 8,由底层文件系统随机决定。

https://issues.apache.org/bugzilla/show_bug.cgi?id=57129


1
投票

我完全同意BalusC提供的答案。只指向添加是指从各个类加载器加载JAR时它确实按字母顺序检查。

我有一种情况可以在我的Web应用程序中加载“XSSFWorkbook”以从excel表读取数据,并且有两个JARS“poi-ooxml-3.9.jar”和“org.eclipse.birt.runtime_4.3.1.v20130918-1142.jar”具有相同的类名和包结构。我简单地将后者重新保留,所以按字母顺序排在前一个旁边,它对我来说是一个技巧。只想分享一样。

祝好运


0
投票

在我们的WebSphere环境中,不同的机器以不同的顺序加载jar。所以我同意user2193008。我们在生产环境中遇到类加载器问题,其中相同的代码在较低的环境中正常工作。我们通过删除lib中的重复jar修复了问题,例如,有两个版本的spring jar,spring_v1.jar和spring_v2.jar,如果classloader首先加载v1,代码工作正常,但如果classloader首先加载v2,则麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.