Java 9重叠未导出的包

时间:2016-11-15 18:05:39

标签: java java-9 java-module

各种资源(infoqjigsaw-devosdir)表示在不同的Java模块中拥有相同的包将导致LayerInstantiationException,即使包是内部的到模块(未出口) 这似乎与requirements所说的完全相反:

  

Java编译器,虚拟机和运行时系统必须确保包含相同名称的包的模块不会相互干扰。如果两个不同的模块包含相同名称的包,那么从每个模块的角度来看,该包中的所有类型和成员都只由该模块定义。

应用程序使用的两个模块是否能够包含同名的私有包?

修改
这是斯坦尼斯拉夫·卢基亚诺夫指出的issue JMPS

2 个答案:

答案 0 :(得分:6)

正如您所讨论的讨论所述,问题是关于类加载器和模块之间的映射。

当您通过类加载器M1加载两个模块M2P都包含未导出的(也称为隐藏的)包CL时,JPMS必须拒绝这样的配置,因为否则两个关键的JPMS原则 - 强大的封装和可靠的配置 - 都可能被打破。通过抛出异常,JPMS实际上实现了您引用的要求,并确保在执行过程中不会发生任何冲突。

另一方面,当您通过两个加载器M1M2加载CL1CL2时,您实际上正在创建两个运行时包{{ 1}}和{CL1, P},因此没有碰撞,{CL2, P}可以实例化。

这里的可用性问题是Layer对应用层的所有模块(从命令行参数创建的“起始”模块)使用单个加载器,这将导致java。这是JPMS列表中的一个未解决的问题,请参见[此处](http://openjdk.java.net/projects/jigsaw/spec/issues/#AvoidConcealedPackageConflicts)。但无论问题的解决方案如何,如果需要,你应该能够通过编写一个小的主类来处理拆分包,这个主类将创建你需要的LayerInstantiationException(BTW一个JPMS感知的应用程序容器可能会为你)。

答案 1 :(得分:1)

这个定义可以解释。它仍然是正确的,因为Jigsaw确保两个模块永远不会通过在发生此类冲突时崩溃类加载来定义共享包。

如果查看Java 9的类加载器实现,可以看到包名称被映射到单个模块。因此,它不可能有两个模块来声明所有权。但是,子父关系中的两个类加载器可能定义相同的包。