Java 9中创建了多少个未命名模块?

10

我正在尝试理解JPMS的工作原理。

来自这里

类路径还没有完全消失。所有JAR(模块化或非模块化)和类都将包含在未命名模块中。与自动模块类似,它导出所有包并读取所有其他模块。但是显然它没有名称。因此,它不能被命名应用程序模块所需和读取。反过来,未命名模块可以访问所有其他模块。

请注意:...on the classpath will be contained in the Unnamed Module。模块是单数。

来自这里

为了兼容性,所有类路径上的代码都被打包成一个特殊的未命名模块,没有隐藏的包,并且完全访问整个JDK。

同样是unnamed module。模块是单数。

我的理解正确吗?这是否意味着在Java9之前开发且未更新为Java9的应用程序将作为一个未命名模块加载?

2个回答

10

我理解得对吗,JPMS 中总是只有一个未命名模块?

简而言之

一般来说,不是这样的。但是我们可以这样说:如果您将一些或所有 JAR 放在类路径上,并且应用程序不创建类加载器来加载任何其他内容,则只需要关注一个未命名模块。

详细说明

每个 ClassLoader 都有自己的未命名模块,它用于表示从类路径加载的类。这是必要的,因为模块系统要求所有内容都在模块中。

正如 nullpointer 的答案 详细解释的那样,应用程序默认使用三个单独的类加载器。它可能会自行启动其自己的类加载器,例如加载插件。但是,如果它不这样做,所有应用程序代码最终都将在系统/应用程序类加载器中,并因此位于同一个未命名模块中。这就是通常只需要关注一个未命名模块的原因。

这是否意味着在 Java9 之前开发并且没有更新到 Java9 的应用程序将被加载为一个未命名模块?

这与代码(应用程序、框架、库)是否针对 Java 9 没有关系,它只取决于您将 JAR 放在类路径上还是模块路径上。

如果它在类路径上,它将与其他类路径内容一起出现在未命名模块中。这适用于没有模块描述符的普通JAR包,也适用于包含一个模块描述符的模块化JAR包。
如果它在模块路径上,它将获得自己的模块。如果是模块化JAR包,则会获得显式模块,就像在模块系统状态中描述的那些 - 普通JAR包会被转换为自动模块(注意复数:每个JAR包一个自动模块)。

6

我理解正确吗,JPMS中总是只有一个未命名模块?

是的,有一个未命名模块。未命名模块与现有的未命名包的概念非常相似。

在使用分层文件系统存储包的Java SE平台实现中,一种典型策略是将每个目录与一个未命名包关联起来;一次只能观察到一个未命名包,即与“当前工作目录”相关联的包。 “当前工作目录”的确切含义取决于主机系统。


这是否意味着在Java9之前开发并且没有升级到Java9的应用程序将被加载为一个未命名模块?

是的,对于那些放置在类路径上的JAR文件,将被视为单个未命名模块。使用未命名模块的自下而上迁移类似于以下示例:(底部向上迁移)

例如,假设上面显示的应用程序最初是为Java SE 8构建的,作为放置在类路径上的一组名称相似的JAR文件。如果我们在Java SE 9上运行它,则JAR文件中的类型将在未命名模块中定义。


这里实际可能会出现的问题是:未命名模块与哪个类加载器相关联?有关未命名模块的模块系统状态对此进行了澄清。

每个类加载器都有自己独特的未命名模块,可以通过新的ClassLoader :: getUnnamedModule方法返回。 如果类加载器加载的类型未在命名模块中定义,则该类型被认为在该加载器的未命名模块中,即类型的Class对象的getModule()方法将返回其加载器的未命名模块。俗称的“未命名模块”就是应用程序类加载器的未命名模块,该加载器从类路径中加载来自任何已知模块未定义的包的类型。

在Java-9中修订的ClassLoader声明如下:

Java运行时具有以下内置类加载器:
- Bootstrap类加载器:虚拟机的内置类加载器... - Platform类加载器:... 为了允许升级/覆盖已定义为平台类加载器的模块,并且已经升级的模块读取了其他平台类加载器及其祖先定义的模块,那么平台类加载器可能需要委托给其他类加载器,例如应用程序类加载器。换句话说,定义为平台类加载器和其祖先之外的类加载器的命名模块中的类可能对平台类加载器可见。 - System类加载器:它也被称为应用程序类加载器,与平台类加载器不同。系统类加载器通常用于在应用程序类路径、模块路径和JDK特定工具上定义类。平台类加载器是系统类加载器的父级或祖先,所有平台类都对其可见。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接