📜  JPMS : Java平台模块系统

📅  最后修改于: 2022-05-13 01:55:08.204000             🧑  作者: Mango

JPMS : Java平台模块系统

JPMS: JPMS 即Java Platform Module System 是Java 9 中引入的一个新特性。借助Java模块系统,我们可以将我们的Java应用程序和我们的Java包打包成Java模块。借助Java模块,我们可以指定该模块的哪些包应该对其他Java模块可见。 Java模块还必须指定需要哪些其他Java模块来完成其工作。
Java平台模块系统有时也被称为Java JigsawProject Jigsaw ,具体取决于。 Jigsaw 是开发期间内部使用的项目名称。后来 Jigsaw 更名为Java Platform Module System。开发 JPMS 的主要目的是使 JRE 更加模块化,即具有可选的更小的 jar 和/或我们可以根据需要仅下载/升级功能。
JPMS/Project Jigsaw 将解决几个主要问题:

  1. 类路径/JAR 地狱
  2. 庞大的单体 JDK
  3. 版本冲突
  4. 安全问题

让我们详细看看它们中的每一个。

  • ClassPath/JAR Hell: Java在运行时搜索类路径中的类和包。假设我们创建了一个应用程序,并且该应用程序需要来自几个 jar 文件的一些类文件,并且我们将这些 jars 添加到类路径中。在编译时,编译器不会检查 jar 中是否存在所需的类文件。它将运行应用程序,并在运行时转到类路径并检查 jar 文件中是否存在所需的类。如果它在那里,那么我们的应用程序将执行得很好。但是出于任何原因,如果 jar 中不存在任何一个类文件,那么它将抛出 NoClassDefFound 错误。我们在引入Java 9 之前就采用了这种方法,并且在运行时使用这种方法可能会出现 NoClassDefFound 错误,这并不好。
    借助Java模块系统,我们可以将我们的Java应用程序和我们的Java包打包成Java模块。除了.class 文件之外, Java模块还包含一个文件,即module-info。 Java文件.每个Java模块都需要一个名为 module-info 的Java模块描述符。 Java必须位于相应的模块根目录中。然而,创建一个模块相对简单。一个模块通常只是一个 jar 文件,其根目录有一个 module-info.class 文件——称为模块化 jar 文件。使用模块化 jar 文件涉及将 jar 文件添加到模块路径而不是类路径。在模块信息中。 Java,我们可以在运行时提及所有依赖项/需要哪些模块。现在在模块信息的帮助下编译。 Java,编译器会知道运行应用程序需要哪些类,并且在编译时只有编译器会检查相应的类/包是否存在于模块中。如果存在所需的类,则代码将成功编译,否则只会在编译时抛出编译错误。这就是Java模块系统解决 classPath/JAR Hell 问题的方式。
  • Massive Monolithic JDK: Monolithic 意味着由一块大石头组成。 JDK 的大单体性质导致了几个问题。它不适合小型设备。小型设备不一定具有容纳所有 JDK 的内存,尤其是当应用程序只使用其中的一小部分时。
Java
class Geeksforgeeks {
    public static void main(String[] args)
    {
        System.out.println(
            "Hello, "
            + "Welcome to Geeksforgeeks!!!");
    }
}


Java
module module4
{
    requires module3;
}


Java
// com.geeksforgeeks.demo.api.geeks is accessible,
// but com.geeksforgeeks.demo.impl.geeksImpl is not
 
module com.geeksforgeeks.demo
{
    exports com.geeksforgeeks.demo.impl;
}


要运行上面的代码,我们需要几个类,如 String、System、Object 等。但即使我们不使用整个 JDK jar,我们也必须持有整个 JDK,甚至不使用 JDK 的 10%。使用这种方法来运行甚至 1KB 的文件,我们需要至少 60MB 的 rt.jar 文件。我们可以用 JPMS 解决这个问题。 Jigsaw 将 JDK 本身分解为许多模块,例如Java.sql 包含熟悉的 SQL 类, Java.io 包含熟悉的 IO 类等。根据需要,我们可以使用适当的模块。无需使用整个 JDK。

  • 版本冲突:

这里我们在类路径中有 4 个 jar 文件。假设 JAR 4 需要一个名为 xyz 的 JAR 3 的 .class文件,而 JAR 2 还包含名为 xyz 的 .class 文件。现在JVM将从左到右搜索xyz类文件,它将从JAR 2中获取以xyz命名的.class文件。现在JVM将在JAR 4中分配JAR 2的xyz.class文件。但是JAR 4需要xyz.class JAR 3 的文件。这里我们将得到版本冲突。在 JPMS 的帮助下,我们可以指定我们想要一个特定 JAR 文件的 .class 文件。我们必须在模块信息中指定。 Java如下:

Java

module module4
{
    requires module3;
}
  • 安全问题:假设我们有一个 JAR 并且在那个 jar 里面我们有 2 个包。
com.geeksforgeeks.demo.api.geeks
com.geeksforgeeks.demo.impl.geeksImpl

这两个包本质上都是公共的。在某些时候,我们可能会决定我们的团队应该使用 geeks 包而不是直接使用 geeksImpl。但是,没有办法在类路径上强制执行。在 JPMS/Jigsaw 中,一个模块包含一个模块信息。 Java文件允许我们明确声明对其他模块公开的内容。

Java

// com.geeksforgeeks.demo.api.geeks is accessible,
// but com.geeksforgeeks.demo.impl.geeksImpl is not
 
module com.geeksforgeeks.demo
{
    exports com.geeksforgeeks.demo.impl;
}