Java Classloader - 如何引用不同版本的 jar
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1553567/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Classloader - how to reference different versions of a jar
提问by mickthompson
This is a common problem. I'm using 2 libraries A.jarand B.jarand these depend on different versions of the same jar.
Let's say that at runtime I need THIS.x.x.x.jar
这是一个常见的问题。我正在使用 2 个库A.jar和B.jar,它们依赖于同一个 jar 的不同版本。
假设在运行时我需要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. 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?).
我可以根据其依赖项编译特定的 jar (A.jar/B.jar),但在运行时我只需要加载 1 个版本。哪一个?
仅加载 1 个依赖项(最新版本)意味着如果库不向后兼容(是否有向后兼容库?),我的代码可能会抛出运行时异常。
Anyway I know that something like OSGi can fix this issue.
I'm wondering what's the old way to fix this kind of problems...
无论如何,我知道像 OSGi 这样的东西可以解决这个问题。
我想知道解决此类问题的旧方法是什么...
Thanks a lot
非常感谢
采纳答案by Vladimir Dyuzhev
"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. That's how, for instance, application servers are able to run both older and newer versions of the same application inside the same JVM.
您提到的“旧方法”(当然也是 OSGI 在幕后使用的一种方法)是为依赖项的两个分支安装自己的 ClassLoader。例如,这就是应用服务器能够在同一个 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 的类加载器加载的类被传递到两个分支。
回答by Brian Agnew
OSGi can fix this problem. An OSGi bundle is nothing more than a jar with additional metadata detailing versions. A bundle has a version number, and will detail version numbers (or ranges) of dependent jars.
OSGi 可以解决这个问题。一个 OSGi 包只不过是一个带有额外元数据详细版本的 jar。捆绑包具有版本号,并将详细说明依赖 jar 的版本号(或范围)。
Take a look at this introductory Javaworld articlefor more information.
有关更多信息,请查看这篇介绍性的 Javaworld 文章。
To solve this without OSGi means having to ensure manually that you compile and run with compatible jars. 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.
要在没有 OSGi 的情况下解决这个问题,意味着必须手动确保您使用兼容的 jar 进行编译和运行。正如您所发现的,这不一定是一项微不足道的任务。由于 jar 不一定标识它们的版本,因此唯一确定的方法是记录/比较校验和或签名。
回答by sfussenegger
As mentioned by KLE, the default approach is to depend on the newer version. 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.
正如 KLE 所提到的,默认方法是依赖较新的版本。无法保证,但大多数情况下这是有效的。可能最好的方法(虽然是一个臃肿的方法)是使用 OSGI 来克服它。
回答by KLE
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
- look on the Internet for users reporting compatibility problems
- write JUnits
- compare the codes in both jars
- 读取新版本 jar 的 WhatsNew 文件
- 在 Internet 上查找报告兼容性问题的用户
- 编写 JUnit
- 比较两个 jar 中的代码
回答by Atul Soman
To refer a basic "oldway" implementation checkout https://github.com/atulsm/ElasticsearchClassLoader
要参考基本的“旧方式”实现结帐https://github.com/atulsm/ElasticsearchClassLoader
This provides an approach to handle non-backward compatible versions of elasticsearch client usage.
这提供了一种处理非向后兼容版本的 Elasticsearch 客户端使用的方法。

