Java Classloader - 如何引用jar的不同版本

时间:2009-10-12 09:28:22

标签: java jar dependencies classloader versions

这是一个常见问题。我正在使用2个库 A.jar B.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这样的东西可以解决这个问题 我想知道解决这类问题的旧方法是什么......

非常感谢

5 个答案:

答案 0 :(得分:7)

你提到的“老方法”(而且一个OSGI当然是在引擎盖下使用)是为你的依赖项的两个分支安装自己的ClassLoader。例如,应用程序服务器就能够在同一个JVM中运行相同应用程序的较旧版本和较新版本。

了解类加载器层次结构。

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

答案 1 :(得分:4)

OSGi可以解决这个问题。 OSGi包只不过是一个带有额外元数据详细说明版本的jar。捆绑包具有版本号,并将详细说明从属罐的版本号(或范围)。

请查看this introductory Javaworld article了解详情。

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

答案 2 :(得分:1)

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


旧的方法是尝试仅依赖一个版本。

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

如果需要,您可以修改一下与旧依赖关系一致的库...
这将需要访问源...


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

  • 阅读WhatsNew文件以获取新版本的jar
  • 在互联网上查找报告兼容性问题的用户
  • 写JUnits
  • 比较两个罐子中的代码

答案 3 :(得分:1)

正如KLE所提到的,默认方法是依赖于较新的版本。没有保证,但大部分时间都有效。可能最好的方式(虽然是一个臃肿的方式)是使用OSGI来克服它。

答案 4 :(得分:1)

引用基本的“oldway”实施结帐https://github.com/atulsm/ElasticsearchClassLoader

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