有人能解释一下从Tomcat中的lib目录加载jar文件的顺序吗? 它按字母顺序排列吗?随机?还是其他一些订单?
答案 0 :(得分:36)
所有这些都在Tomcat's ClassLoading HOW-TO中描述。它不一定按字母顺序排列。如果您发现了这种行为,那么如果您打算让Web应用程序在服务器之间移植,那么它应该绝对不是。例如,Tomcat 6“巧合地”命令它,但Tomcat 8没有。
总结,加载顺序如下:
JRE/lib
,然后是server.loader
)WEB-INF/classes
,然后是WEB-INF/lib
)common.loader
,然后是Tomcat/lib
)shared.loader
)如果您想保证在 JAR Y之后加载JAR X,那么您需要将JAR X放在以后出现的中的一个中上面的列表。
但是有一些例外,tomcat docs
中提到了这些例外情况最后,Web应用程序类加载器将始终首先委托JavaEE API类来执行Tomcat(Servlet,JSP,EL,WebSocket)实现的规范。 Tomcat中的所有其他类加载器都遵循通常的委托模式。
这意味着如果webapp包含任何JavaEE类(javax.*
),那么tomcat将忽略它。
对于每个加载器,只要需要导入/执行并且尚未加载,JVM就会按顺序加载这些类。
答案 1 :(得分:32)
实际上,是按字母顺序排列! (在特定目录中,例如原始海报提到的'lib'目录。)
更具体地说,如果您查看Tomcat 6的源代码,在类FileDirContext
中,方法list()
会在找到的jar文件名数组上调用Arrays.sort()
。 / p>
我也手动测试了这个。我用一个调用HelloWorld.getGreeting()
的JSP创建一个war,并将两个几乎相同的包含HelloWorld
略有不同版本的jar放入WEB-INF / lib目录中。一个说“你好,世界”,另一个说“再见,残酷的世界”。
如果我将“Hello,world”版本命名为a.jar,并将“goodbye”版本命名为b.jar,并重新启动Tomcat,则会收到“Hello”文本。如果我用另一个方式命名罐子并重新启动Tomcat,我会得到“Goodbye”文本。
据我所知,此行为未记录,未指定,不应依赖。但它现在是按字母顺序排列的。
答案 2 :(得分:23)
在WEb-INF / lib文件夹中订购加载的罐子。
对于tomcat 5-7,顺序是按字母顺序排列的。它使用sort。
对于tomcat 8,由底层文件系统随机决定。
答案 3 :(得分:1)
我完全同意BalusC提供的答案。只指向添加是指从相应的类加载器加载JAR时它确实按字母顺序检查。
我有一种情况要加载" XSSFWorkbook"在我的网络应用程序中从excel表读取数据,并有两个JARS" poi-ooxml-3.9.jar"和" org.eclipse.birt.runtime_4.3.1.v20130918-1142.jar"具有相同的类名和包结构。我简单地将后者重新保留,所以按字母顺序排在前一个旁边,它对我来说是一个技巧。只想分享一样。
祝你好运
答案 4 :(得分:0)
在我们的WebSphere env中,不同的机器以不同的顺序加载jar。所以我同意user2193008。我们在生产环境中遇到类加载器问题,在较低环境中相同的代码可以正常工作。我们通过删除lib中的重复jar来解决问题,例如,有两个版本的spring jar,即spring_v1.jar和spring_v2.jar,如果classloader首先加载v1,代码可以正常工作,但是如果classloader首先加载v2,则麻烦。