【问题标题】:Order of loading jar files from lib directory从 lib 目录加载 jar 文件的顺序
【发布时间】:2011-07-25 09:21:49
【问题描述】:

谁能解释从Tomcat中的lib目录加载jar文件的顺序? 是按字母顺序吗?随机?还是其他顺序?

【问题讨论】:

标签: java tomcat classloader


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    其实是按字母顺序排列的! (在特定目录中,例如原始海报提到的“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,我会得到“再见”文本。

    据我所知,这种行为没有记录,没有指定,也不应该被依赖。但它是按字母顺序排列的——暂时。

    【讨论】:

    • +1 用于指出已发布文档的“陷阱”
    • 我可以为 Tomcat 5+6 确认这一点,但目前有问题,因为 Tomcat 8.0.9 的行为并非如此!
    • 不应依赖 Tomcat 6 的字母顺序。它不是 Servlet 规范的一部分,依赖这种行为应该被视为与规范相反。 Tomcat 的更高版本不按字母顺序排列,因此您肯定不想要依赖这种行为。
    【解决方案3】:

    这一切都在Tomcat's ClassLoading HOW-TO 中进行了描述。它不一定按字母顺序。如果您观察到这种行为,那么如果您打算让您的 web 应用程序在服务器之间保持可移植性,则应该绝对不依赖它。例如,Tomcat 6“巧合地”订购了它,但 Tomcat 8 没有。

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

    1. 引导程序/系统(JRE/lib,然后是server.loader)
    2. webapp 库(WEB-INF/classes,然后是WEB-INF/lib)
    3. 常用库(common.loader,然后是Tomcat/lib)
    4. webapp 共享库 (shared.loader)

    如果您想保证 JAR X 是在 JAR Y 之后加载的,那么您需要将 JAR X 放在 稍后 出现的位置之一上面的清单。

    但也有例外,在tomcat docs 中提到

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

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

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

    【讨论】:

    • 是否解释了单个目录中文件的加载顺序?
    • @Joachim:它只是在 JVM 需要它的时候加载。 OP 更多地要求搜索顺序。
    • 感谢 BalusC。我会检查需要工件的顺序,希望能够得出一个合理的解决方案
    • 在未来,最好发布一个关于具体问题的清晰简洁的问题(例如“我有 x.jar 到位 X,但我得到 NoClassDefFoundError, blahblah”)而不是(广泛)关于您认为是问题根源的主题的问题。
    • 那个链接没有提到 shared.loader [显然它在 tomcat 6 stackoverflow.com/a/6258314/32453 中默认为 common 但如果你定义了一个,它在 common AFAICT 之前使用,所以 4 应该在 3 之前? ]
    【解决方案4】:

    在 WEB-INF/lib 文件夹中加载 jar 的顺序。

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

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

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

    【讨论】:

    • 您是在回答还是提出新问题?
    • 猜一猜:)。我在回答。
    • 请花一些时间重新格式化您的答案,使其看起来像一个答案。查看How do I write a good answer,了解如何改进答案。
    【解决方案5】:

    我完全同意 BalusC 提供的答案。唯一需要补充的是,当从相应的类加载器加载 JAR 时,它会检查字母顺序。

    我有一种情况要在我的 Web 应用程序中加载“XSSFWorkbook”以从 excel 表中读取数据,并且有两个 JARS“poi-ooxml-3.9.jar”和“org.eclipse.birt.runtime_4.3.1.v20130918-1142” .jar”具有相同的类名和包结构。我只是将后者重新命名,因此按字母顺序排列在较早的那个旁边,这对我来说是个窍门。只是想分享一下。

    祝你好运

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 2014-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      相关资源
      最近更新 更多