拆分包:Java 模块与密封罐

Split Packages: Java Modules vs Sealed Jars

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

是的,模块中的包总是隐式密封的。这在 the documentation of the Package class:

中指定

A Package automatically defined for classes in a named module has the following properties:

  • The name of the package is derived from the binary names of the classes. Since classes in a named module must be in a named package, the derived name is never empty.
  • The package is sealed with the module location as the code source, if known.
  • The specification and implementation titles, versions, and vendors are unspecified.
  • Any annotations on the package are read from package-info.class as specified above.

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

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

相比之下,命名模块的每个包都必须明确属于整个模块层中的单个模块,并且模块层可以跨越多个 class 加载器,例如boot layer 跨越 bootstrap 加载器、平台加载器和应用程序加载器。

这会影响 class 加载过程。仍然用于未命名模块的旧加载方式具有 class 加载器委派,其中每个加载器首先查询其父加载器。当父加载器失败时,class 路径条目线性查询 class 直到找到 class。

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