Dan*_*iel 10 java java-platform-module-system java-9
我预计可以在myModuleA中使用ie Guava-19,在myModuleB中使用guava-20,因为jigsaw模块有自己的类路径.
假设myModuleA使用Iterators.emptyIterator(); - 在guava-20中删除,myModuleB使用新的静态方法FluentIterable.of(); - 番石榴-19没有.不幸的是,我的测试是否定的.在编译时,它看起来很好.与运行时相反,结果是NoSuchMethodError.意味着,类加载器中的第一个类决定哪个失败.
与底层耦合的封装?我找到了自己的理由.由于传递依赖性会产生与以前相同的问题,因此无法支持它.如果在ModuleA和ModuleB中的签名中发生版本冲突的guava类依赖于它.应该使用哪个班级?
但为什么我们可以通过互联网阅读"拼图 - 模块系统停止类路径地狱"?我们现在有多个较小的"类似路径",但问题相同.这不仅仅是一个问题,而是一个不确定性.
Nic*_*lai 13
首先是一个更正:你说模块有自己的类路径,这是不正确的.应用程序的类路径保持不变.与之并行的是模块路径,但它基本上以相同的方式工作.特别是,所有应用程序类都由相同的类加载器加载(至少默认情况下).
对于所有应用程序类,只有一个类加载器也解释了为什么不能有同一个类的两个版本:整个类加载基础结构是基于完全限定的类名称足以标识具有类加载器.
这也为多个版本打开了解决方案的路径.就像之前你可以通过使用不同的类加载器来实现它.模块系统本机方式是创建附加层(每个层都有自己的加载器).
那么模块系统用模块地狱取代类路径地狱呢?好吧,如果不创建新的类加载器,仍然无法使用同一个库的多个版本,因此这个基本问题仍然存在.
另一方面,由于拆分包,现在至少在编译或启动时出错.这可以防止程序巧妙地行为不端,这也不是那么糟糕.
从理论上讲,可以在应用程序中使用同一库的不同版本。实现这一目标的概念:分层!
当您在引擎盖下学习拼图时,会发现一个完整的章节专门讨论该主题。
基本上,您的想法是可以使用这些层进一步对模块进行分组。层是在运行时构造的;他们有自己的类加载器。含义:在一个应用程序中绝对有可能在不同版本中使用模块-它们只需要进入不同的层即可。如图所示-java / jigsaw上的工作人员正在积极地讨论这种“多版本支持”。这不是一个晦涩的功能-它旨在在一个引擎盖下支持不同的模块版本。
这时唯一的免责声明:不幸的是,那里没有“完整的”源代码示例(据我所知),因此,我只能链接到该Oracle演示文稿。
换句话说:有一些种类的解决方案,在地平线上的这个版本的问题-但它会花费更多的时间,直到使在现实世界中的代码的经验与这个新想法。准确地说:您可以拥有由不同的类加载器隔离的不同层。有没有支持,将允许您“同一个对象”使用modV1和modV2在同一时间。您只能有两个对象,一个使用modV1,另一个使用modV2。
(德国读者可能想在这里看看-该出版物包含有关图层主题的另一篇介绍)。