JDK的模块化

Posted 麦克叔叔每晚10点说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK的模块化相关的知识,希望对你有一定的参考价值。

在Java模块化系统引入之前,JDK的运行时库包括了重量级的rt.jar,该jar文件的总大小超过60M,包含了大量的运行时类。为了重构整个Java平台,也为了Java能够在轻量级语言解决方案越来越占主导地位的情况下让Java语言继续旺盛的生命力,JDK团队引入了JDK的模块化设计,这个决定可能是关键性的。


在过去的20年中,JDK的若干次发布,每一次都会包含许多新的特性,因此也增加了大量的类。以CORBA为例,它在上世纪90年代的时候被认为是企业级计算的未来,当然现在几乎没有人记得它了,然而用于支持CORBA的类仍然被包含在rt.jar包里面,也就是说,无论你有没有用到这些类,只要你的应用程序是分布式的,你都不得不带着它们一起运行。这样做的直接后果是浪费了磁盘空间、内存空间,以及CPU资源(需要增大CPU运行耗时)。对于资源受限的硬件载体,或者云端的资源,这样就产生了浪费,也增加了成本(云端资源是按需申请的,能省就省)。


那么我们可不可以直接移除这些不需要的类呢?不能这么简单执行,因为我们需要考虑每次发布之后的向前兼容,直接删除API会导致JDK升级后一些老的应用程序不可用。JDK引入模块化管理方式后,我们只需要忽略包含CORBA的模块就可以了。


当然,分解单体型(monolithic)的JDK并不仅仅是移除过时(例如CORBA)的类。JDK包含的很多技术都是这样的,对于一些人有用,对于另一些人则是无用的,但是并不是说它们过时了,仅仅是应用程序不需要使用。Java语言一直以来就存在安全性漏洞,通过模块化设计可以减少类的应用,自然也就降低了漏洞发生的几率。


截止目前,JDK9大约有超过90个平台模块,这种方式取代了以往的单一型大库形态。平台模块是JDK的一部分,它和应用程序模块是不一样的,应用程序模块是由程序员自己创建的。但是从技术层面来看,平台模块和应用程序模块又没有什么区别。每一个平台模块构造了一个JDK功能,从日志到XML的支持,等等,覆盖了原有单一型JDK的功能。在JDK9里,所有的模块都需要在外部显示地定义与其他模块之间的依赖关系,这就好比我们买可拆装家具时的各模块之间的榫头,你一看就知道需要和哪些其他模块进行拼接,而一些其他模块都可以拿来公用的模块,比如java.logging,你就会发现很多模块都会应用它。也正是由于引入了模块化,JDK内部终于在各个模块之间有了清晰的界限,互相的引用关系终于清晰了。

注意,按照JDK9目前的模块化设计理念,所有的依赖关系都是指向向下方向的,不会出现编译时的各模块间环形依赖情况,你自己编写的应用程序模块也需要避免这种情况发生。


模块资源介绍


一个模块包含模块名称、相关的代码和资源,这些都被保存在称为module-info.java的模块描述文件里,以下面这个文件为例,描述java.prefs平台模块。

清单1 module-info.java

module java.prefs{

requires java.xml;

exports java.util.prefs;

}

代码清单1内包含了requires和exports两个关键字,逐一解释:


requires关键字表示了依赖关系,这里明确模块需要依赖java.xml模块,如果没有依赖生命,java.prefs模块在编译时会拒绝执行编译命令。这一点是向Maven借鉴的,使用前必须声明才能使用。


exports关键字表示了其他模块如何可以引用java.prefs包,由于模块化编程已经把强封装性设置成了默认选项,因此只有当包被显式地声明导出(就是这里的exported),导出为本例的java.util.prefs包。Exports是针对原有的访问方式(public、protected、private)的一个补充,是针对强一致性的补充,Java9之后,public仅仅是针对模块内部类之间的访问权限,如果你想要从外部能够应用模块内部类,你必须要exports。


注意,模块名由于是全局变量,所以需要是全局唯一的。


HelloWorld案例


接下来简单介绍一个HelloWorld示例。如清单2所示,HelloModularWorld类的main函数负责打印字符串“Hello World, new modular World!”。

清单2 HelloModularWorld类

package org.michael.demo.jpms;

public class HelloModularWorld {

public static void main(String[] args) {

System.out.println("Hello World, new modular World!");

}

}

为了实现模块化,需要在工程的根目录下创建一个名为module-info.Java的类,内容如清单3所示:

清单3 module-info.Java源码

module org. michael.demo.jpms_hello_world {

// this module only needs types from the base module 'Java.base';

// because every Java module needs 'Java.base', it is not necessary

// to explicitly require it - I do it nonetheless for demo purposes

requires Java.base;

// this export makes little sense for the application,

// but once again, I do this for demo purposes

exports org.michael.demo.jpms;

}

如代码清单3所示,引用了Java.base,输出至org.michael.demo.jpms包。接下来开始编译,如清单4所示。

清单4 编译模块化系统

$ Javac

-d target/classes

${source-files}

$ jar --create

--file target/jpms-hello-world.jar

--main-class org.michael.demo.jpms.HelloModularWorld

-C target/classes .

$ Java

--module-path target/jpms-hello-world.jar

--module org. michael.demo.jpms_hello_world


就这个简单的示例来看,除了增加了一个文件、编译时的差别替换为使用模块路径方式(module path),以及工程没有了manifest文件以外,其他和Java9之前的编程/编译方式是一样。

发个小广告!!!走过路过,不要错过!新书来啦!!!

JDK的模块化
JDK的模块化
JDK的模块化

这里有你想买的书!

http://product.dangdang.com/23949549.html#ddclick_reco_reco_relate

麦克叔叔每晚十点说


以上是关于JDK的模块化的主要内容,如果未能解决你的问题,请参考以下文章

JDK模块化之模块的基础概念

JDK模块化之模块的基础概念

JDK9-初尝模块化

JDK模块化之简单示例

JDK模块化之简单示例

JDK的模块化