拆分包:Java模块vs密封jar



Sealed Packages/Jars和Java Module System都不允许在多个jar中拆分包。这是否意味着模块中包含的所有包都是隐式密封的?如果不是,明确地密封罐子会改变什么?

是的,模块中的包总是隐式密封的。这是在Package类的文档中指定的:

为命名模块中的类自动定义的Package具有以下属性:

  • 包的名称来源于类的二进制名称。由于命名模块中的类必须位于命名包中,因此派生名称永远不能为空。
  • 包被密封,模块位置作为代码源,如果知道。
  • 规范和实现标题、版本和供应商未指定。
  • 包上的任何注释都是从上面指定的package-info.class中读取的。

我还做了一个快速测试来验证模块包上的isSealed()确实返回true。但是,必须注意的是,(命名的)模块和包之间的关系具有基本性质,因此与isSealed()返回true的事实无关。后者是旧API与新特性交互的自然方式。

未命名模块的密封包只影响特定类装入器的运行时包,因为每个类装入器可以有一个同名的包,这被认为是不同的运行时包。

相反,命名模块的每个包必须明确地属于整个模块层中的单个模块,并且模块层可以跨越多个类加载器,例如引导层跨越引导加载器,平台加载器和应用程序加载器。

这会影响类加载过程。旧的加载方式仍然用于未命名模块,其特点是类装入器委托,其中每个装入器首先查询其父装入器。当父加载器失败时,将线性查询类的类路径条目,直到找到一个类。

当一个模块层被初始化时,所有的包名和它们所属的模块都被记录下来,所以当尝试加载一个类时,包名可以从限定名中派生出来,甚至在类被加载之前就可以映射到模块上,因此,只需要查询模块的已知源。