【发布时间】:2011-07-25 09:21:49
【问题描述】:
谁能解释从Tomcat中的lib目录加载jar文件的顺序? 是按字母顺序吗?随机?还是其他顺序?
【问题讨论】:
标签: java tomcat classloader
谁能解释从Tomcat中的lib目录加载jar文件的顺序? 是按字母顺序吗?随机?还是其他顺序?
【问题讨论】:
标签: java tomcat classloader
在我们的 WebSphere 环境中,不同的机器以不同的顺序加载 jar。所以我同意user2193008。我们在生产环境中遇到类加载器问题,其中相同的代码在较低的环境中运行良好。我们通过删除lib中重复的jar来解决问题,例如,有两个版本的spring jar,spring_v1.jar和spring_v2.jar,如果classloader先加载v1,代码可以正常工作,但是如果classloader先加载v2,那就麻烦了。
【讨论】:
其实是按字母顺序排列的! (在特定目录中,例如原始海报提到的“lib”目录。)
更具体地说,如果您查看 Tomcat 6 的源代码,在类 FileDirContext 中,方法 list() 对找到的 jar 文件名数组调用 Arrays.sort()。
我也手动测试过。我使用调用HelloWorld.getGreeting() 的JSP 创建了一个war,并将两个几乎相同的jar 包含稍微不同版本的HelloWorld 放入WEB-INF/lib 目录。一个说“你好,世界”,另一个说“再见,残酷的世界”。
如果我将“Hello, world”版本命名为a.jar,将“goodbye”版本命名为b.jar,然后重新启动Tomcat,我会得到“Hello”文本。如果我反过来命名 jar 并重新启动 Tomcat,我会得到“再见”文本。
据我所知,这种行为没有记录,没有指定,也不应该被依赖。但它是按字母顺序排列的——暂时。
【讨论】:
这一切都在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 X 是在 JAR Y 之后加载的,那么您需要将 JAR X 放在 稍后 出现的位置之一上面的清单。
但也有例外,在tomcat docs 中提到
最后,Web 应用程序类加载器总是首先为 JavaEE API 类委托 Tomcat 实现的规范(Servlet、JSP、EL、WebSocket)。 Tomcat 中的所有其他类加载器都遵循通常的委托模式。
这意味着如果 webapp 包含任何 JavaEE 类 (javax.*),那么它将被 tomcat 忽略。
对于每个加载器,只要类需要导入/执行并且尚未加载,JVM 就会按顺序加载它们。
【讨论】:
NoClassDefFoundError, blahblah”)而不是(广泛)关于您认为是问题根源的主题的问题。
在 WEB-INF/lib 文件夹中加载 jar 的顺序。
对于 tomcat 5-7,顺序是按字母顺序排列的。它使用排序。
对于tomcat 8 是由底层文件系统随机决定的。
【讨论】:
我完全同意 BalusC 提供的答案。唯一需要补充的是,当从相应的类加载器加载 JAR 时,它会检查字母顺序。
我有一种情况要在我的 Web 应用程序中加载“XSSFWorkbook”以从 excel 表中读取数据,并且有两个 JARS“poi-ooxml-3.9.jar”和“org.eclipse.birt.runtime_4.3.1.v20130918-1142” .jar”具有相同的类名和包结构。我只是将后者重新命名,因此按字母顺序排列在较早的那个旁边,这对我来说是个窍门。只是想分享一下。
祝你好运
【讨论】: