小编典典

在分离的Java平台模块中使用依赖关系的不同版本

java

我希望有可能在myModuleA中使用Guava-19,在myModuleB中使用guava-20, 因为拼图模块具有自己的类路径。

假设myModuleA使用Iterators.emptyIterator();
-已在guava-20中删除,而myModuleB使用新的静态方法FluentIterable.of();
-番石榴19中没有。不幸的是,我的测试是否定的。在编译时,看起来不错。与运行时相比,结果是NoSuchMethodError。意味着,类加载器上的第一个类决定哪个失败。

与底层耦合的封装?我找到了自己的理由。由于传递依赖项将具有与以前相同的问题,因此无法支持。如果模块A和模块B中的签名中发生了具有版本冲突的番石榴类,则取决于它。应该使用哪个类?

但是,为什么为什么在整个互联网上我们都能读到“拼图-模块系统停止了类路径”?现在,我们有多个较小的“相似类路径”具有相同的问题。它比问题更不确定。


阅读 217

收藏
2020-11-13

共1个答案

小编典典

版本冲突

首先进行更正:您说模块具有自己的类路径,这是不正确的。应用程序的类路径保持不变。与此并行的引入了模块路径,但实际上它的工作方式相同。特别是,所有应用程序类均由同一类加载器加载(至少默认情况下)。

所有应用程序类都只有一个类加载器,这也解释了为什么同一类不能有两个版本:整个类加载基础结构是基于一个完全限定的类名足以识别带有类加载器。

这也为多种版本的解决方案打开了道路。就像之前,您可以通过使用不同的类加载器来实现。模块系统执行此操作的本机方法是创建其他(每个层都有自己的加载器)。

模块地狱?

那么模块系统是否将类路径hell替换为module hell?好吧,如果不创建新的类加载器,仍然不可能使用同一库的多个版本,因此,这个基本问题仍然存在。

另一方面,由于包拆分,现在至少在编译或启动时会出错。这样可以防止程序巧妙地执行错误操作,这也不是那么糟糕。

2020-11-13