【问题标题】:Loading two classes in different JARs在不同的 JAR 中加载两个类
【发布时间】:2011-04-28 19:58:25
【问题描述】:

我在不同的 JAR 中有两个具有相同包的类。直到以前的版本,这两个类都是相同的,所以我在加载它们时没有问题。现在,其中一个添加了一个新方法,如果我想访问它,我不仅应该使用该包导入类,我还需要确保具有正确类的 jar 在类路径中排在第一位。

javac -classpath "%classpath%;a.jar;b.jar" MyClasses..

a.jar 有我的新方法的类。

现在,当我的应用程序投入生产时,我如何确保这一点,它被部署为 EAR 文件,所有库都在 WEB-INF/lib 下?

我如何知道哪个 jar 优先于另一个?是不是像 a.jar 这样的字母顺序优先于 b.jar?

我已经阅读了这个safe-class-imports-from-jar-files 线程并了解了如何编写自定义类加载器,但是有没有更好更简单的解决方案呢?因为我只是要在当前项目的整个 JAR 中访问这个方法,而编写一个类加载器似乎有点矫枉过正。

请不要问我“为什么同一类在不同的 JAR 中具有相同的包?”这完全超出我的控制,需要一些时间才能纠正。

环境细节:IBM WAS 6.1 在他们的 1.5 Java 上。

如果我没有多大意义,请再问我一些问题。提前致谢!

【问题讨论】:

  • 好的,谢谢大家的回答。最后,尽管我不想说,任何人都可以建议的唯一真正的解决方法是删除重复项。除此之外,我可以选择将我的 jar 添加到引导类路径或应用服务器的类路径中,但该选项似乎也不可行,因为部署不是由我完成的。我会尽快接受答案。非常感谢,再次感谢。

标签: java classpath classloader websphere-6.1


【解决方案1】:

您可以尝试更改服务器的启动脚本,并使用java -Xbootclasspath 在引导类路径中指定具有正确类的 jar .... 否则无法保证 2 个 jar 中的哪一个会首先加载。

【讨论】:

    【解决方案2】:

    据我所知,从 WEB-INF/lib 加载 jar 的顺序是任意的——我问了一个关于 JBOSS 的类似问题并得到了回复(来自 RedHat),这取决于 java.io.File.listFiles() 返回的顺序它们在(这不是保证顺序)。

    自定义类加载器是一种选择,但您是否考虑过重新打包 jar - 删除重复的类?

    【讨论】:

    • @DaveHowes 谢谢,但就像我说的那样,删除重复项需要一些时间,因为它必须经过某些级别的批准。另外,您可以发布指向您的问题的链接吗?这可能会有所帮助。
    • 实现此目的的一个 hackey 方法可能是将“正确”的 jar 放在应用服务器类路径上并使用“父优先”类加载。不过,这将是一种脆弱的方法。
    • 是的,它是一个 hack,而且很脆弱。但是,可能没有更好的办法了。
    • @DavesHowes 我在Sun tutorials 的帮助下编写了这个custom classloader,它尝试加载我指定的类并使用反射打印出它的方法。但是当它首先出现在类路径中时,它会加载我的另一个 jar 的类。我做错什么了吗?如果我的正确 jar 在类路径中排在第二位,我觉得即使 Custom ClassLoader 也无济于事。
    【解决方案3】:

    Websphere 允许您指定在搜索类时查询特定应用程序的类加载器的顺序(类加载器是分层结构的,从加载 JRE 类的最高层到加载 WAR 中的类加载器)。

    在应用部署过程中,您可以指定搜索类时查询类加载器的顺序。有两种模式 - 父级优先(即首先查询最顶层的类加载器)和父级最后(首先查询应用程序类加载器)。这可以在 EAR 和 WAR 级别上指定。

    将重复的 jar 打包到应用程序中的不同位置(例如,一个到 EAR 的类路径,另一个到 WAR 的 WEB-INF/lib)并适当地设置类加载器排序可能会解决您的问题。但是,如果您的两个 JAR 必须处于同一级别(例如 WEB-INF/lib),则无法指定在加载重复的类时将使用哪一个。

    【讨论】:

    • 对,他们都在应用程序级别:(
    • 将一个放在 EAR 的类路径或 appserver 的 ext 类路径中。 IMO 没有其他机会这样做。
    • @asgs,这对你来说基本上是一个可怕的情况。唯一“真正”的解决方案是修复 jar 以澄清依赖关系,除非您可以做一些 真正 时髦的事情,例如将 OSGi 嵌入您的 Web 应用程序中。这会奏效,但考虑到问题所在,治疗比疾病更糟糕。
    【解决方案4】:

    一个应用程序中 JAR 的顺序可能是按字母顺序排列的,但应用程序的顺序可能不是。此外,这取决于服务器如何处理类加载,即它是替换现有类还是跳过新类。

    尽管您已经说过,但我仍然想给出这样的建议:在一个应用程序中部署的多个 JAR 中使用相同的类(例如,这可能发生在版本化的 jar 中)总是一个坏主意。你最好花时间来解决这个问题,而不是试图搞乱类加载。

    【讨论】:

    • @Andreas 我读到了,但如前所述,我不认为搞乱类加载是值得的。这可能是加快清理过程(以及随之而来的批准)的一个原因。 - 编辑:asgs 并没有说绝对没有办法修复它,它似乎需要一段时间。
    【解决方案5】:

    这可能会很模糊,但我确实记得通过在给定应用程序的 WAS 管理控制台中搞乱并使用他们的 web 重新排列相关 JAR 文件来解决这个问题 很长时间用户界面。不确定这在您的情况下是否可以接受,但值得一试,以防 一切 失败。

    【讨论】:

    • 我猜你指的是 WAS 管理控制台中可用的类加载模式选项。
    【解决方案6】:

    假设您对部署有一定的控制权,请自行修复类加载。通过以相反的加载顺序将它们解压缩到同一目录中,然后重新压缩到一个新的 jar 中,自己组合有问题的 jar。然后使用新的组合 jar 部署应用程序。没有重复的类,问题解决了。

    或者,在部署之前从 jar 中删除重复的类。

    【讨论】:

    • 嘿,你是对的,但如果我被允许的话,我会非常愿意这样做的。
    • @jtalhborn,除了签入文件并等待部署发生外,我实际上没有任何控制权:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 2018-03-14
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多