java 9 之后的新特性之平台模块化系统

前言


Java平台模块化系统(Module System)是从Java 9开始引入的一项新特性,它允许将一个Java应用程序或库划分为多个模块,并使这些模块之间明确定义依赖关系,以提高代码的可维护性、安全性和可扩展性。下面我们来详细了解一下Java平台模块化系统的相关内容。

什么是Java平台模块化系统


Java平台模块化系统是一种组织和部署Java代码的方法,它可以将Java应用程序或库划分为多个模块,每个模块都是一个独立的单元,可以定义自己的接口和实现,同时明确规定与其他模块之间的依赖关系。

这种方法的优点包括:

  • 可以更好地控制代码的可见性和访问权限;

  • 减少代码冲突和依赖问题;

  • 提高代码的可维护性、可测试性和可扩展性。

模块的定义


模块是一个可重用的、独立的、自包含的代码单元,由一组相关的类、接口、枚举和注解组成

模块可以被用来封装代码、提供抽象接口和实现、控制访问权限和可见性,以及明确规定与其他模块之间的依赖关系。

每个模块都必须包含一个模块描述文件(module-info.java),用于指定模块的名称、版本、依赖关系和导出的包。

模块描述文件是一个Java源代码文件,可以使用Java编译器进行编译,并打包成一个JAR文件,可以在Java虚拟机中加载和执行。例如,一个名为"com.example.myapp"的模块可以包含以下模块描述文件:

module com.example.myapp {
    requires java.base;
    requires com.example.mylib;
    exports com.example.myapp.api;
    exports com.example.myapp.impl to com.example.myapp.plugin;
}

上面的模块描述文件指定了该模块的名称为"com.example.myapp",它需要Java的基础模块(java.base)和自定义的"com.example.mylib"模块。同时,它将"com.example.myapp.api"包导出给其他模块使用,但只将"com.example.myapp.impl" 导出给"com.example.myapp.plugin"使用。

设计背景是什么,最初是为了解决什么技术痛点


Java平台模块化系统最初是在Java SE 9中引入的。它的设计背景是Java开发人员在使用Java平台的过程中,面临了很多技术痛点,如代码冲突、版本不兼容、难以控制的类路径等等问题。

在传统的Java开发中,开发人员通常需要将所有的Java类和依赖库打包成一个JAR文件,并将这个JAR文件添加到classpath中。这种方式虽然简单易用,但是在复杂的应用程序中,很容易出现类冲突和版本不兼容问题。

例如,当一个应用程序同时使用了多个依赖库,这些依赖库中可能会有相同的类名或者不同版本的类,这就会导致运行时的类冲突和异常。

为了解决这些问题,Java平台模块化系统被设计出来了。它将一个Java应用程序或库划分为多个模块,每个模块都是一个独立的单元,可以定义自己的接口和实现,同时明确规定与其他模块之间的依赖关系。这种方式更加灵活,可以控制代码的可见性和访问权限,减少代码冲突和依赖问题,提高代码的可维护性、可测试性和可扩展性。

总的来说,Java平台模块化系统是为了解决Java开发中出现的代码冲突、版本不兼容、类路径难以控制等问题而设计的,它提供了一种更加灵活、可控制、可维护的Java应用程序部署方式。

适用范围?


Java平台模块化系统是针对所有使用JDK开发的项目的,包括使用Java SE、Java EE、Java ME等各种Java平台的应用程序和库。

模块化系统提供了一种更加灵活、可控制、可维护的Java应用程序部署方式,可以帮助开发人员更好地组织和管理Java代码,减少代码冲突、版本不兼容等问题,提高代码的可测试性、可维护性和可扩展性。

虽然Java平台模块化系统最初是在Java SE 9中引入的,但是它也可以用于Java SE 11、Java SE 17等后续版本的JDK。

以下是一些按照Java平台模块化系统的理念开发的开源项目:

  • Apache Maven 4.x:Apache Maven是一个流行的Java构建工具,它已经支持Java 9的模块化系统,并计划在未来的版本中增加更多的功能。

  • Spring Framework 5.x:Spring Framework是一个流行的Java应用程序开发框架,它已经支持Java 9的模块化系统,并使用了模块化系统来组织它的代码。

  • Eclipse IDE 2021.x:Eclipse是一个流行的Java IDE,它已经支持Java 9的模块化系统,并使用模块化系统来组织它的插件和功能。

  • JUnit 5.x:JUnit是一个流行的Java测试框架,它已经支持Java 9的模块化系统,并使用模块化系统来组织它的代码。

  • Guava 29.x:Guava是一个流行的Java库,它提供了许多实用的工具类和函数。它已经支持Java 9的模块化系统,并使用模块化系统来组织它的代码。

可以看到,这些项目都是广泛使用的Java开发的工具或框架,并且都具有一定的规模和复杂性。

由于Java平台模块化系统是为了解决Java应用程序的复杂性问题而设计的,因此这些项目最适合使用模块化系统来组织它们的代码和依赖项。

此外,这些项目还可以使用模块化系统来提高它们的性能、可维护性和可扩展性。当然,除了这些平台级的产品,还有一些应用程序也可以采用Java平台模块化系统,比如JavaFX应用程序和基于模块化的应用服务器等。

提供一个开发示例


当你使用Java平台模块化系统时,你需要定义一个module-info.java文件来指定你的模块信息和依赖关系。下面是一个简单的开发示例:

  1. 首先,我们创建一个Java项目,包含两个类:Main和Utils。

  1. 在项目的根目录下创建一个module-info.java文件,用来定义模块信息和依赖关系:

module com.example.app {
    exports com.example.app;
    requires com.example.utils;
}
在这个module-info.java文件中,我们定义了一个名为com.example.app的模块,它导出了com.example.app包,并声明了对com.example.utils模块的依赖关系。
  1. 在Utils类中定义一个方法,用来输出一段字符串:

package com.example.utils;

public class Utils {
    public static void print(String message) {
        System.out.println(message);
    }
}
  1. 在Main类中调用Utils类中的方法:

package com.example.app;

import com.example.utils.Utils;

public class Main {
    public static void main(String[] args) {
        Utils.print("Hello, world!");
    }
}
  1. 最后,我们使用javac命令编译我们的代码,并使用java命令运行它:

javac -d out --module-source-path src -m com.example.app
java --module-path out -m com.example.app/com.example.app.Main
其中,-d选项指定编译后的class文件输出目录,--module-source-path选项指定模块源代码所在的目录,-m选项指定要运行的模块和主类。
这个示例演示了如何使用Java平台模块化系统来定义模块信息和依赖关系,并使用javac和java命令来编译和运行Java应用程序。当你的项目变得更加复杂时,你可以使用更多的模块和依赖关系来组织你的代码,并使用更多的工具来管理你的Java应用程序

和java 模块化有关的问题


java.lang.IllegalAccessError:xxx类A (in unnamed module @0x1517365b) cannot access class xxx类B (in module xx模块C ) because module xx模块C does not export xx目录 to unnamed module @0x1517365b


此错误消息表明,从未命名模块中的xxx类A模块访问 xx模块C 中的 xxx类B 类时存在问题。

发生错误是因为模块 xx模块C 没有将包导出到未命名的模块,这阻止了类 xxx类A 访问类 xxx类B。

解决方案


  1. 在启动Java应用程序时,在命令行选项中添加

——add-exports xx模块C/xxx类B= ALL-UNNAMED
这将把包从xx模块C模块导出到所有未命名的模块。
  1. 可以修改xxx类A模块的module-info.java文件,添加一个require xx模块C;、
    和一个exports xxx类A的包;
    声明。这将显式地声明对 xx模块C 模块的依赖,并导出xxx类A的包。

请注意,这些解决方案可能并不适用于所有场景,因为它们涉及更改应用程序的类路径或模块结构。因此,您应该在实现每种方法之前仔细考虑它们的含义。

后记


对于一些企业级Web应用程序,使用Java平台模块化系统并不是必需的,因为这些应用程序往往比较简单,其代码和依赖项通常都可以用传统的方式来组织和管理。此外,许多现有的Web应用程序也不支持Java平台模块化系统,因此在这些应用程序中使用模块化系统可能会带来一些麻烦。然而,随着Java平台模块化系统的成熟和应用场景的不断扩展,未来可能会有更多的企业级Web应用程序采用这种理念。

你可能感兴趣的:(java,java,jvm)