这是一个常见问题。我正在使用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这样的东西可以解决这个问题 我想知道解决这类问题的旧方法是什么......
非常感谢
答案 0 :(得分:7)
你提到的“老方法”(而且一个OSGI当然是在引擎盖下使用)是为你的依赖项的两个分支安装自己的ClassLoader。例如,应用程序服务器就能够在同一个JVM中运行相同应用程序的较旧版本和较新版本。
了解类加载器层次结构。
在你的设置中,棘手的部分是关节点,来自两个分支的类相遇。两个分支都不能使用加载到另一个分类中的类。使其工作的方法是确保只有引导类加载器(JRE类)或MY.jar的类加载器加载的类才传递给两个分支。
答案 1 :(得分:4)
OSGi可以解决这个问题。 OSGi包只不过是一个带有额外元数据详细说明版本的jar。捆绑包具有版本号,并将详细说明从属罐的版本号(或范围)。
请查看this introductory Javaworld article了解详情。
要解决此问题,无需OSGi意味着必须手动确保您使用兼容的jar进行编译和运行。正如您所发现的,这不一定是一项微不足道的任务。由于jar不一定能识别它们的版本,因此唯一可靠的方法是记录/比较校验和或签名。
答案 2 :(得分:1)
许多库都向后兼容。但不是全部..
旧的方法是尝试仅依赖一个版本。
使用相同版本(最新版本)编译两者可能更安全 至少你得到编译时错误,而不是运行时错误。
如果需要,您可以修改一下与旧依赖关系一致的库...
这将需要访问源...
请注意,编译时兼容性也不能保证正确的运行时行为。这是一步,然后你可以:
答案 3 :(得分:1)
正如KLE所提到的,默认方法是依赖于较新的版本。没有保证,但大部分时间都有效。可能最好的方式(虽然是一个臃肿的方式)是使用OSGI来克服它。
答案 4 :(得分:1)
引用基本的“oldway”实施结帐https://github.com/atulsm/ElasticsearchClassLoader
这提供了一种处理elasticsearch客户端使用的非向后兼容版本的方法。