【问题标题】:Java Classloader - how to reference different versions of a jarJava Classloader - 如何引用不同版本的 jar
【发布时间】:2010-12-05 22:20:00
【问题描述】:

这是一个常见问题。我正在使用 2 个库 A.jarB.jar,它们依赖于同一个 jar 的不同版本。
假设在运行时我需要 THIS.x.x.x.jar

MY.jar   
     -> A.jar -> THIS.1.0.0.jar
     -> B.jar -> C.jar -> THIS.5.0.0.jar

我可以针对其依赖项编译特定的 jar (A.jar/B.jar),但在运行时我只需要加载 1 个版本。哪一个?
仅加载 1 个依赖项(最新版本)意味着如果库不向后兼容(是否有向后兼容的库?),我的代码可能会引发运行时异常。

无论如何,我知道像 OSGi 这样的东西可以解决这个问题。
我想知道解决此类问题的旧方法是什么...

非常感谢

【问题讨论】:

  • 有可能实现这一点吗?OSGi 如何提供帮助?我们再次引入了对 OSGi 的依赖,这是典型产品软件开发(尤其是嵌入式)的开销

标签: java jar dependencies classloader versions


【解决方案1】:

许多库都向后兼容。但不是全部..


老办法是尝试只依赖一个版本。

使用相同版本(最新)编译两者可能更安全。
至少你会得到编译时错误,而不是运行时错误。

如果需要,您可以稍微修改与旧依赖项一起使用的库...
这将需要访问源...


请注意,编译时兼容性也不能保证正确的运行时行为。这是一步,然后你可以:

  • 读取新版本 jar 的 WhatsNew 文件
  • 在 Internet 上查找报告兼容性问题的用户
  • 编写 JUnit
  • 比较两个 jar 中的代码

【讨论】:

    【解决方案2】:

    OSGi 可以解决这个问题。 OSGi 包只不过是一个带有附加元数据详细版本的 jar。一个包有一个版本号,并且会详细说明依赖 jar 的版本号(或范围)。

    查看this introductory Javaworld article 了解更多信息。

    在没有 OSGi 的情况下解决这个问题意味着必须手动确保您使用兼容的 jar 进行编译和运行。正如您所发现的那样,这不一定是一项微不足道的任务。由于 jar 不一定能识别它们的版本,因此唯一可靠的方法是记录/比较校验和或签名。

    【讨论】:

      【解决方案3】:

      正如 KLE 所提到的,默认的方法是依赖于较新的版本。无法保证,但大多数情况下这是有效的。可能最好的方法(虽然臃肿)是使用 OSGI 来克服它。

      【讨论】:

        【解决方案4】:

        您提到的“旧方式”(当然也是 OSGI 在后台使用的一种方式)是为您的依赖项的两个分支安装您自己的 ClassLoader。举例来说,这就是应用程序服务器能够在同一个 JVM 中运行同一应用程序的旧版本和新版本的方式。

        了解类加载器层次结构。

        在您的设置中,棘手的部分是两个分支的类相遇的联合点。两个分支都不能使用加载到另一个分支中的类。使其工作的方法是确保只有引导类加载器(JRE 类)或 MY.jar 的类加载器加载的类被传递到两个分支。

        【讨论】:

          【解决方案5】:

          要参考基本的“旧方式”实施结帐https://github.com/atulsm/ElasticsearchClassLoader

          这提供了一种处理非向后兼容版本的弹性搜索客户端使用的方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-02-22
            • 1970-01-01
            • 2014-01-06
            • 1970-01-01
            • 1970-01-01
            • 2023-03-08
            • 1970-01-01
            相关资源
            最近更新 更多