图:模块化手机概念

一、什么是Java模块化Java模块化(module)是Java9及以后版本引入的新特性。

官方对模块的定义为:一个被命名的,代码和数据的自描述集合。( the module, which is a named, self-describing collection of code and data)。

早在Java7的时候就被提出,但由于其复杂性,不断跳票,直到Java9才有,那么Java模块化到底是什么,在实际开发中又有什么用呢?

简单来说,就是把jar进一步掰碎。

一个jar可以有多个module,一个module可以有多个package。
从代码结构上看,jar > module > package > class/interface。

那么怎么掰碎Jar包呢?

Java从自身做了一个典范,把JDK里面大部分Jar都掰成了一个个module

JDK1.8结构:

JDK17将其拆成一个一个jmod:

而且,官方提供了文档对每一个模块进行了介绍:

模块描述
java.base定义 Java SE 平台的基础 API。
java.compiler定义语言模型、注释处理和 Java 编译器 API。
java.datatransfer定义用于在应用程序之间和应用程序内传输数据的 API。
java.desktop定义 AWT 和 Swing 用户界面工具包,以及用于 辅助功能、音频、成像、打印和 JavaBeans。
java.instrument定义允许代理 检测在 JVM 上运行的程序。
java.logging定义 Java 日志记录 API。
java.management定义 Java 管理扩展 (JMX) API。
java.management.rmi定义 Java 管理扩展插件 (JMX) 远程 API 的RMI 连接器。
java.naming定义 Java 命名和目录接口 (JNDI) API。
java.net.http定义 HTTP 客户端和 WebSocket API。
java.prefs定义首选项 API。
java.rmi定义远程方法调用 (RMI) API。
java.scripting定义脚本 API。
java.se定义 Java SE 平台的 API。
java.security.jgss定义 IETF 通用安全服务 API (GSS-API) 的 Java 绑定。
java.security.sasl定义对 IETF 简单身份验证和安全层的 Java 支持 (萨斯尔)。
java.smartcardio定义 Java 智能卡 I/O API。
java.sql定义 JDBC API。
java.sql.rowset定义 JDBC 行集 API。
java.transaction.xa定义用于在 JDBC 中支持分布式事务的 API。
java.xml定义 Java API for XML Processing (JAXP)、Streaming API for XML (StAX), XML 的简单 API (SAX) 和 W3C 文档对象模型 (DOM) API。
java.xml.crypto定义 XML 加密的 API。
jdk.accessibility定义辅助技术实现者使用的 JDK 实用程序类。
jdk.attach定义附加 API。
jdk.charset提供字符集不在(主要是双字节和 IBM 字符集)。java.base
jdk.compiler定义系统 Java 编译器及其命令行等效项javac的实现。
jdk.crypto.cryptoki提供 SunPKCS11 安全提供程序的实现。
jdk.crypto.ec提供 SunEC 安全提供程序的实现。
jdk.dynalink定义用于动态链接对象高级操作的 API。
jdk.editpad提供jdk.jshell使用的编辑板服务的实现。
jdk.hotspot.agent定义热点功能配置代理的实现。
jdk.httpserver定义特定于 JDK 的 HTTP 服务器 API。
jdk.jartool定义用于操作 Java 归档 (JAR) 文件的工具, 包括jar和jarsigner工具。
jdk.javadoc定义系统文档工具及其命令行等效项javadoc的实现。
jdk.jcmd定义用于诊断和排除 JVM 故障诊断的工具 如JCMD,JPS,JSTAT工具。
jdk.jconsole定义 JMX 图形工具,jconsole, 用于监视和管理正在运行的应用程序。
jdk.jdeps定义用于分析 Java 库和程序中依赖关系的工具, 包括JDEPS、JavaP和JDEPRSCAN工具。
jdk.jdi定义 Java 调试接口。
jdk.jdwp.agent提供 Java 调试线路协议 (JDWP) 代理的实现。
jdk.jfr定义 JDK 飞行记录器的 API。
jdk.jlink定义用于创建运行时的jlink工具 图像,用于创建和操作的JMod工具 JMOD文件,以及用于检查的jimage工具 类和资源的特定于 JDK 实现的容器文件。
jdk.jshell此模块提供对 Java 编程语言“片段”评估工具,例如 读取-评估-打印循环 (REPL),包括jshell工具。
jdk.jsobject定义 JavaScript 对象的 API。
jdk.jstatd定义用于启动守护程序的jstatd工具 用于远程监控 JVM 统计信息的 JSTAT 工具。
jdk.localedata提供美国区域设置以外的区域设置的区域设置数据。
jdk.management为 JVM 定义特定于 JDK 的管理接口。
jdk.management.agent定义 JMX 管理代理程序。
jdk.management.jfr定义 JDK 飞行记录器的管理接口。
jdk.naming.dns提供 DNS Java 命名提供程序的实现。
jdk.naming.rmi提供 RMI Java 命名提供程序的实现。
jdk.net定义特定于 JDK 的网络 API。
jdk.pack定义用于将 JAR 文件转换为压缩包200 文件的工具 并将打包文件转换为 JAR 文件,包括 pack200 和unpack200工具。
jdk.rmic定义用于生成存根的rmic编译器和 对远程对象使用 Java 远程方法协议 (JRMP) 的框架。
jdk.scripting.nashorn提供 Nashorn 脚本引擎的实现和 用 ECMAScript 5.1 编写的程序的运行时环境。
jdk.sctp为 SCTP 定义特定于 JDK 的 API。
jdk.security.auth提供接口和各种身份验证模块的实现。javax.security.auth.*
jdk.security.jgss定义 GSS-API 的 JDK 扩展和 SASL 的实现 GSSAPI机制。
jdk.xml.dom定义不属于一部分的 W3C 文档对象模型 (DOM) API 的子集 的 Java SE API。
jdk.zipfs提供 zip 文件系统提供程序的实现。

以上是机器翻译,原文:https://docs.oracle.com/en/java/javase/11/docs/api/index.html

二、模块化有什么好处

好处就是将jar的功能精细化,可以按需使用。

猜测是为了解决Java项目尤其是JVM一直被诟病比较臃肿的问题,怎么解决臃肿呢?砍就完了!

  • 进一步规范Java的依赖

  • 按需使用,最小化加载,减少冲突,减小Java应用大小

  • 可以对耦合性封装性进一步约束

  • 使调用权限管理更清晰,提高系统的安全性

精简JRE就是模块化一个典型的应用:
1、maven编译,打包项目,打包依赖jar到libs
2、使用新版JDK自带的jdeps找出依赖的模块
3、使用新版JDK自带的jlink制作自定义JRE

三、如何创建模块1、创建一个Java项目或者module

2、在代码根路径下创建文件module-info.java

定义模块名称,依赖的模块,以及导出的模块

3、编译Java项目

在编译后的目录中可以看到module-info.class文件

4、创建jmod文件

使用jmod create命令:

命令格式:
jmod create --class-path module-info.class文件对应的路径 输出的jmod文件名

四、如何启动可执行模块

上面咱们创建的模块中是有Main入口的可执行模块,
那么能不能像java -jar一样执行这个模块呢?

答案是肯定的:

使用java –module命令:

命令格式:
java --module-path 模块文件所在路径 模块名称/包名.main类名

执行后,就可以把java程序给运行起来啦:

五、既然这么好,我们常用的Spring有没有支持?

看到这里,同学们可能发现了,这需要整个Java生态开发者所有人按规范对自己的Jar进行模块化才能达到最优效果,而且实际开发过程中定义和管理自己的模块及模块之间的依赖关系是比较复杂的事情。

这里有一个关于Java模块化算不算复杂以及有没有必要的知乎问题,供大家参考:
https://www.zhihu.com/question/610866431?utm_id=0

那么我们常用的Spring有没有被模块化打动,也按规范进行模块化了呢?
至少到Spring5还没有,但是这里有一些答案:

1:Declare Spring modules with JDK 9 module metadata

SpringFramework官方的回答:
https://github.com/spring-projects/spring-framework/issues/18079

机器翻译:JDK 9的Jigsaw计划旨在允许将模块元数据(module-info.java)添加到框架和库jar中,同时保持它们与JDK 8的兼容性。让我们对Spring Framework 5.0的模块尽可能地这样做。然而,我们可能无法以这种方式表达我们的可选依赖安排,在这种情况下,我们可能不得不采用“自动模块”方法来实现#18289中更温和的目的。

2:Any plans for Java 9 Jigsaw (module) of Spring projects?

https://stackoverflow.com/questions/43685081/any-plans-for-java-9-jigsaw-module-of-spring-projects

作者:京东科技 周波