我对Java9模块的理解
一、前言
主要介绍Java 9平台模块系统(JPMS: Java 9 Platform Module System),它是Java自诞生以来最重要的新软件工程技术。是模块化项目Jigsaw的产物,帮助开发人员在构建、维护和扩展软件系统(尤其是大型系统)时提高生产力。
二、历史
Java SE自1995年诞生以来,从用于资源受限设备的小型应用程序(如物联网(IoT)和其他嵌入式设备中的应用程序)到关键业务和关键任务系统等大型应用程序,一应俱全。随着发展,java有大量的遗留代码,但是直到现在,Java平台一直提供一站式的解决方案。但很多时候很多功能并没有被广泛使用,但是Java平台也没能使用模块化,因此诞生了Project Jigsaw^1。
Java SE平台的模块化一直很难实现。 JSR 277:在2005年的Java 7第一次提出了Java模块系统。此JSR后来被JSR 376:Java Platform Module System取代,并打算在Java 8实现。Java 8 发布的时候并没有带来JPMS,但是带来了JEP 161: Compact Profiles(定义Java SE平台规范的一些概要,可以不需要整个平台,应用程序就可以部署和运行在小型设备上。)
我们可以简单看出Oracle将Java API定义了三个紧凑配置,感兴趣可以自行查阅相关资料。
1 | compact1 compact2 compact3 |
JPMS最终推迟到了2017年9月,在Java 9中得以实现。
三、快速上手
1. 传统项目
在模块化出来之前,我们的项目运行依赖于各种class或者jar文件,如当我们编译完SpringBoot项目,由于其依赖了各种starter,我们的运行命令是这样的:
可以看出,**-classpath**后面的参数除了我们项目编译后class文件夹外,还有各种第三方的jar包,密密麻麻,好在有Maven、Gradle等这类自动构建工具帮我们打包生成清单文件,最终生成的jar包,我们要运行仅需输入如:java -jar jeremy.jar
便可运行我们的项目。
2. Java module项目
创建一个Java工程,新建主类com.jeremytsai.module.App
1 | public class App { |
src下创建module-info.java文件
1 | module jeremy { |
编译项目,生成字节码文件
1 | │ module-info.class |
运行模块
1 | java -p . -m jeremy/com.jeremytsai.module.App |
至此,我们就完成的第一个模块的开发。其中**-p后面的参数是模块路径,-m后面的是<模块>[/<主类>]**。
3. 传统项目与Java module项目的区别
传统项目是
1 | package -> class/interface |
Java module 项目是
1 | module -> package -> class/interface |
我们反编译module-info.class看看
1 | module jeremy { |
多了一个默认项,requires java.base;
,意思指的是运行我们这个项目仅需java.base这个模块即可,这样我们就可用只包含java.base模块的jre加上我们的代码便可以运行我们的项目。非模块项目的jre是不能精简的。
JDK8 中包含有完整jre,其中rt.jar是非常大的,在1.8.0_202版本中有60.6MB,而JDK9中并没有jre,取而代之的是jmods文件夹。
1 | java.activation.jmod |
这里能看到我们所需要依赖的 java.base。有了这些java 模块,我们就可以打包运行我们项目所需的最小环境,这样在资源受限的小型设备中就能有更好的发挥。
四、JPMS的特性
Project Jigsaw的主要目标是:
使开发人员更轻松地构建和维护库和大型应用程序
总体上提高Java SE平台实现(特别是JDK)的安全性和可维护性
改善应用程序性能
使Java SE Platform和JDK能够按比例缩小规模,以用于小型计算设备和密集型云部署。
这里重点讲讲安全性问题,以往我们可以通过反射获取各种公开/非公开的属性/方法,由于public属性的存在,Java过于开放。经常访问到一些非核心/内部使用的公开API。
引入JPMS后,我们只能访问模块公开的API,开发者也可以很好隐藏自己内部public的一些非关键的API了。也能有效阻止反射获取私有属性/字段。反射在编译过程并不会报错,即便**setAccessible(true)**,最终还是得到 InaccessibleObjectException运行时异常。