Java 类加载器 - 如何引用 jar 的不同版本
-
20-09-2019 - |
题
这是一个常见问题。我正在使用 2 个库 罐子 和 B.jar 这些取决于同一个 jar 的不同版本。
假设在运行时我需要 这个.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引擎盖下肯定使用)是安装自己的ClassLoader为你的依赖的两个分支。这是怎么了,例如,应用程序服务器能够运行在同一个JVM内部新旧版本的同一应用程序。
阅读关于类加载器的层次结构。
在您的设置中,棘手的部分是接头的点,其中来自两个支路的类满足。无论是分支机构可以采用加载到另外一个班。使它工作的方法是确保只有通过引导类加载器(JRE类)或MY.jar的类装载器装载的类传下来的两个分支。
其他提示
许多库都是向后兼容的。但不是所有的..
旧的方法是尝试仅依赖一个版本。
使用相同版本(最新)编译两者可能更安全。
至少你会得到编译时错误,而不是运行时错误。
如果需要,您可以稍微修改一下与旧依赖项一起使用的库......
这需要访问源...
请注意,编译时兼容性也不能保证正确的运行时行为。这是一步,然后您可以:
- 阅读 WhatsNew 文件以获取新版本的 jar
- 在 Internet 上查找报告兼容性问题的用户
- 编写 JUnit
- 比较两个jar中的代码
正如KLE所提到的,默认的方法是依赖于较新版本。谁也不能保证,但大多数的这个作品的时候。可能是最好的方式(而被臃肿一个)是利用OSGI克服它。
要参照基本的 “oldway” 实施结帐 https://github.com/atulsm/ElasticsearchClassLoader
此提供了一种方法来处理elasticsearch客户端使用的非后向兼容的版本。