简体   繁体   English

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

[英]Java Classloader - how to reference different versions of a jar

This is a common problem. 这是一个常见问题。 I'm using 2 libraries A.jar and B.jar and these depend on different versions of the same jar. 我正在使用2个库A.jarB.jar ,这些库依赖于同一个jar的不同版本。
Let's say that at runtime I need THIS.xxxjar 假设在运行时我需要THIS.xxxjar

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

I can compile the specific jar (A.jar/B.jar) against its dependency but at runtime I've to load only 1 version. 我可以针对它的依赖编译特定的jar(A.jar / B.jar)但是在运行时我只能加载1个版本。 Which one? 哪一个?
Loading only 1 dependency (the latest version) means that my code will probably throw runtime exceptions if the libraries are not Backward Compatible (are there Backward Compatible libraries out there?). 仅加载1个依赖项(最新版本)意味着如果库不是向后兼容的,那么我的代码可能会抛出运行时异常(那里有向后兼容的库吗?)。

Anyway I know that something like OSGi can fix this issue. 无论如何,我知道像OSGi这样的东西可以解决这个问题。
I'm wondering what's the old way to fix this kind of problems... 我想知道解决这类问题的旧方法是什么......

Thanks a lot 非常感谢

"Old way" you mentioned (and the one OSGI certainly uses under the hood) is to install your own ClassLoader for both branches of your dependencies. 你提到的“旧方法”(以及OSGI当然使用的一种方法)是为依赖关系的两个分支安装自己的ClassLoader。 That's how, for instance, application servers are able to run both older and newer versions of the same application inside the same JVM. 例如,应用程序服务器就能够在同一个JVM中运行相同应用程序的较旧版本和较新版本。

Read about classloader hierarchy. 阅读类加载器层次结构。

In your setup, the tricky part is the joint point, where classes from both branches meet. 在你的设置中,棘手的部分是联合点,两个分支的类在这里相遇。 Neither branches can use classes loaded into another one. 两个分支都不能使用加载到另一个分类中的类。 The way to make it work is to make sure only classes loaded by boot classloader (JRE classes) or classloader of MY.jar are passed down to both branches. 使其工作的方法是确保只有引导类加载器(JRE类)或MY.jar的类加载器加载的类才传递给两个分支。

OSGi can fix this problem. OSGi可以解决这个问题。 An OSGi bundle is nothing more than a jar with additional metadata detailing versions. OSGi包只不过是一个带有额外元数据详细说明版本的jar。 A bundle has a version number, and will detail version numbers (or ranges) of dependent jars. 捆绑包具有版本号,并将详细说明从属罐的版本号(或范围)。

Take a look at this introductory Javaworld article for more information. 有关更多信息,请查看这篇介绍性的Javaworld文章

To solve this without OSGi means having to ensure manually that you compile and run with compatible jars. 要在没有OSGi的情况下解决这个问题,就必须手动确保使用兼容的jar进行编译和运行。 As you've discovered that's not necessarily a trivial task. 正如您所发现的,这不一定是一项微不足道的任务。 Since jars don't necessarily identify their versions, the only sure way to do this to record/compare checksums or signatures. 由于jar不一定能识别它们的版本,因此唯一可靠的方法是记录/比较校验和或签名。

Many libraries are backward compatible. 许多库是向后兼容的。 But not all.. 但不是所有的..


The old way is to try to depend from only one version. 旧方法是尝试仅依赖一个版本。

It is probably safer to compile both with the same version (latest). 使用相同版本(最新版本)编译两者可能更安全。
At least you get compile-time errors, instead of runtime errors. 至少你得到编译时错误,而不是运行时错误。

If needed, you can modify a little bit your library that works with the old dependency... 如果需要,您可以修改一下与旧依赖项一起使用的库...
This would require access to the source... 这需要访问源...


Please note that compile-time compatibility will not guarantee correct runtime behavior either. 请注意,编译时兼容性也不能保证正确的运行时行为。 It is one step, then you can: 这是一步,你可以:

  • read the WhatsNew file for the new version of the jar 阅读WhatsNew文件,了解新版本的jar
  • look on the Internet for users reporting compatibility problems 在互联网上查找报告兼容性问题的用户
  • write JUnits 写JUnits
  • compare the codes in both jars 比较两个罐子里的代码

As mentioned by KLE, the default approach is to depend on the newer version. 正如KLE所提到的,默认方法是依赖于较新的版本。 There is no guarantee, but most of the time this works. 没有保证,但大部分时间都有效。 Probably the best way (while being a bloated one) is using OSGI to get over it. 可能最好的方式(虽然是一个臃肿的方式)是使用OSGI来克服它。

To refer a basic "oldway" implementation checkout https://github.com/atulsm/ElasticsearchClassLoader 引用基本的“oldway”实现checkout https://github.com/atulsm/ElasticsearchClassLoader

This provides an approach to handle non-backward compatible versions of elasticsearch client usage. 这提供了一种处理elasticsearch客户端使用的非向后兼容版本的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM