Java平台模块系统(JPMS)是Java SE 9的主要新功能。在本文中,Java Champion和JAX Londonspeaker的Stephen Colebourne介绍JPMS,并介绍它可能出现的问题。
Java Platform Module System java平台模块系统,简称JPMS。是java SE 9的最主要的一个新功能。
本文就来细细介绍下JPMS。
JPMS ,是一个全新的模块系统,作为项目Jigsaw来开发,目的就是要提高java编码的抽象级别。
这个项目的主要目标就是:
• 让java SE平台和JDK 更容易地运行到小型计算设备上;
• 提高Java SE平台实现的安全性和可维护性,特别是JDK;
• 改善应用程序性能;
• 让开发更容易的管理和组织lib和大应用程序,针对SE和EE平台。
为了实现这些目标,我们建议为Java SE平台设计和实现一套标准模块系统,并将该系统应用于平台本身和JDK。模块系统应该足够强大,可以对JDK和其他大型遗留代码库进行模块化,同时还要对开发人员友好。
然而,愿望是美好的,项目目标并不总是能够得到满足。
什么是JPMS Module?
JPMS是对Java库,语言和运行时的更改。这意味着它会影响开发人员日常代码编写的整个堆栈,因此JPMS可能会产生很大的影响。出于兼容性原因,大多数现有代码可以忽略Java SE 9中的JPMS,这可能被证明是非常有用的。
关键的概念要点是JPMS向JVM增加了一个新概念,这个概念叫模块(modules)。以前,代码被组织成字段(fields),方法(methods),类(classes),接口(interfaces)和包(packages),现在, Java SE 9中有了一个新的结构元素 - 模块。
• 类是字段和方法的容器
• package是类和接口的容器
• module 则是package的容器。
是不是感觉因垂死听。世界有点变了。
因为这是一个新的JVM元素,它意味着运行时可以应用强大的访问控制。在Java 8的时候,开发人员可以通过将某个类的方法声明为private,这样其他类就看不到该方法了。在Java 9中呢?开发人员可以让一个包(pacakge)不被其他模块看到就是一个包可以隐藏在一个模块中。
在理论上,能够隐藏软件包对于应用程序设计来说应该是一个很大的好处。不再需要把一个包命名为“impl”或“internal”,然后Javadoc声明“请不要使用此包中的类型”。不幸的是,生活不会那么简单。
但创建模块相对简单。一个模块通常只是一个jar文件,在文件的根目录下有一个module-info.class文件,就是一个模块化jar文件。该文件是从源代码库中的module-info.java文件创建的。
使用模块化jar文件涉及将jar文件添加到模块路径(modulepath )而不是类路径(classpath)。如果一个模块化jar文件在类路径上,它将不会充当模块,而module-info.class将被忽略。因此,虽然模块路径上的模块化jar文件将具有由JVM执行的隐藏包,但类路径上的模块化jar文件根本就不会有隐藏的包。
其他现有模块系统
Java一直以来都有其他模块系统,最有名的是OSGi和JBoss模块。但, JPMS与这些系统几乎没什么相似之处。
OSGi和JBoss模块在没有JVM的直接支持下而存在,但依然为模块提供一些额外的支持。它是通过在其自己的类加载器中启动每个模块来实现的,这样做是可以的,但也有自己的问题。
毫无意外的,自然而然的,这些现存的模块系统的所在组织的专家就被纳入到正式的开发JPMS的专家组。但是,这种关系并不协调。基本上,JPMS作者(Oracle)已经开始构建一个JVM扩展,可以用于可以被描述为模块的东西,而现有的模块系统却是从今天存在的大型应用程序中获取真实用例和棘手的案例的经验和价值。
阅读“模块”相关的文章时,请注意你正在阅读的文章的作者是否来自OSGi / JBoss模块设计阵营。(我从来没有主动使用OSGi或JBoss模块,尽管我已经使用Eclipse和其他在内部使用OSGi的工具。)
module-info.java
module com.opengamma.util { requires org.joda.beans; // 这是模块名,不是包名 requires com.google.guava; exports com.opengamma.util; //这是包名,不是模块名 }
module-info.java文件其实就是一个定义模块的说明书(这里只说到最重要的一些,还有其他的)。它也是一个.java文件,但是,语法与以前见过的任何.java文件无关,是完全不同的。
在编辑这个文件的时候,你通常需要思考两个关键问题:
1、该模块依赖什么。
2、它导出什么。
这个模块声明说com.opengamma.util取决于(需要)org.joda.beans和com.google.guava。它暴露一个包叫com.opengamma.util。使用模块路径(modulepath)(由JVM执行)时,所有其他软件包都将被隐藏。
与java.base(JDK的核心模块)有一个隐含的依赖关系。请注意,JDK本身也是模块化的,所以如果要依赖于Swing,XML或Logging,则需要表示依赖关系。
module org.joda.beans { requires transitive org.joda.convert; exports org.joda.beans; exports org.joda.beans.ser; }
这个模块声明说org.joda.beans依赖于(requires)org.joda.convert。 “requires transitive(依赖传递)”,而不是简单的“requires”,意味着任何需要org.joda.beans的模块也可以查看并使用org.joda.convert中的包。这里用于Joda-Beans的方法,返回类型来自Joda-Convert。如虚线显示。
module org.joda.convert { requires static com.google.guava; exports org.joda.convert; }
这个模块声明说org.joda.convert取决于(requires)com.google.guava,但是在编译时只需要“requires static”,而不是简单的“requires”。这是一个可选的依赖关系。如果Guava在模块路径上,则Joda-Convert将能够看到并使用它,如果不存在Guava,则不会发生错误。如虚线显示。
访问规则
当在使用了JVM访问规则的模块路径上运行模块化jar时,如果有下列条件时,那么程序包A中的代码可以看到包B中的类型:
• 类型为 public;
• 包B被其模块导出(exports);
• 包含程序包A的模块和包含程序包B的模块存在依赖关系。
因此,在上面的示例中,模块com.opengamma.util中的代码可以看到包裹org.joda.beans,org.joda.beans,ser,org.joda.convert和Guava导出的任何包。但是,它看不到包org.joda.convert.internal(因为它没有导出)。另外,代码模块com.google.guava看不到程序包org.joda.beans或org.joda.convert中的代码,因为没有模块化的依赖关系。
JPMS可能会出什么问题?
上述基础介绍足够简单。于是你可能想着就用这些基础知识就可以来构建应用程序了,并从“隐藏软件包”中获得一些好处。不幸的是,事情并没有这么单纯,有很多地方可能出错。
总结
不要对Java 9中的JPMS - 模块感到太兴奋。以上只是对module-info.java文件可能的内容和JPMS的限制的总结。如果你正在考虑模块化您的lib或应用程序,请等一会儿,直到所有内容变得更清晰再说吧!
ps:本文只是一个JPMS的基础,后面会介绍更多Java平台模块系统的细节。
本文分享自 ImportSource 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!