如何评价java osgi9模块化

Java9 手把手教你实现模块化Java9 手把手教你实现模块化冰点服务百家号IntelliJ IDEA 2017.1 支持Java9的模块化特性 (Project Jigsaw)。 在此版本,模块文件中还支持基于特定名称与关键字的自动补全功能 code completion, 并且你可以快速斧正你项目中的模块化代码。So,那就让我们来一探究竟什么是模块化工程。首先,我们创建一个普通的模块工程 IntelliJ IDEA module 其中包含了改变世界的伟大的 “Hello World” 。A simple applicationIntelliJ IDEA 会引导你在工程中为你的模块创建一个module-info.javaCreate new module-info.javamodule-info.java 将为你提供一个基础的模块代码结构。Default module-info.java一切听指挥,党会指引你正确的道路!此时,当你在按照以往那样使用一个Java类时,你就会看到模块化带来的新姿势。Error using LoggerHere,IntelliJ IDEA可以帮助你找出问题所在,并提出修复建议。Add requires to module-info.java如你所料,进行这个操作之后IntelliJ IDEA对module-info.java文件进行了正确的更改。Requires added当然,你也可以尝试自己编辑module-info.java文件,IDEA 会给你完整的补全和提示信息。Code completion in module-info.java快速修复不仅可用于标准Java模块,还可帮助您自己编写模块代码。如果您尝试访问另一个IntelliJ IDEA模块中的代码,从一个模块的内部来使用模块化特性 (module-info.java文件中会有提示), IntelliJ IDEA 将会提示你如果没有进行正确的更改,是不能运行的。Using other modules首先,有很多提示来帮助你完成更改,所以,一旦module-info.java文件所在的模块下有java文件,你可以快速补齐后面的包路径。Code completion for exports回到这个被导入模块的类中来,使用Alt 和 Enter 来获取fix建议。这里有两个步骤:firstly, 模块 one需要依赖模块two。secondly,一旦此操作完成,模块one的module-info.java文件就能关联模块two。Quick fixes for using modules这里有两个模块,需要格外注意的是:firstly, the IntelliJ IDEA modules 你可能已经熟悉; and secondly, 新的 Java 9 (Jigsaw) 模块被指定使用module-info.java。 要使用Java模块化特性,每个Java 9模块都需要对应于IntelliJ IDEA模块。还要注意的是(IntelliJ IDEA 2017.1中的最后一个示例所示),需要声明IntelliJ IDEA模块依赖关系以及Java 9模块依赖关系。所以在最后一个例子中,模块one依赖模块two:IntelliJ IDEA module dependencies但是在module-info.java文件中也需要声明它是关联模块two的:本文由百家号作者上传并发布,百家号仅提供信息发布平台。文章仅代表作者个人观点,不代表百度立场。未经作者许可,不得转载。冰点服务百家号最近更新:简介:冰点—我的平台你做主!作者最新文章相关文章点击这里,将文章分享到自己的动态
探索Java 9的模块化
随着 java 9 的正式发布,java生态又迎来了新的变革,模块化是最重要的变化。java 9由于Jigsaw项目Java 9 跳票了很多次,你可能已经听说过很多关于模块、模块化和其他的一些东西,而这些都是什么?模块化是什么鬼?模块化平台对我们来说意味什么?什么是java平台模块化系统(JPMS)?它将在java生态中带来什么革命性变化?这篇文章是我对JDK中关于模块化系统发生的重要变化的探索。我将解释什么是模块化,你为什么需要它,你怎么样能创建自己的模块化项目。JPMSWhat & Why可维护性是软件设计和演进的过程中最重要的问题,我们想要一个松耦合、高内聚、高可读性并且一眼就能理解的代码库。我们以package的形式设计和组织类文件,到目前为止还不错,但是当我们有数百个package的时候,它们之间的依赖关系一眼是看不完的。因此我们需要比package更多的组织代码库的方法,来提高代码库的可维护性。另外一个问题是java classpath,它是如何运行我们的代码的,所有的jar类和类库都是堆积在classpath中。当这些jar文件中的类在运行的时候有多个版本的时候,java的ClassLoader仅能加载那个类的一个版本。在这种情形下,你的程序的运行就会有歧义,歧义是一件非常坏的事情。这个问题是频繁出现的,它被称为是“”。另外一个关于classpath的问题是,它不遵循“Fail First”原则。你可能会丢失一些类文件,这些文件存在于classpath中但是在生产环境不存在,这个问题只能在运行时报出JavaClassDefError异常的时候,你才能确定缺失了什么类文件。最后,classpath的最大问题在于“封装”,在classpath中的每个类互相访问,这是违反“封装”特性的。我们想隐藏内部的API,这就是我们为什么需要另一个级别的封装(更强的封装),并且对package中的类的访问做控制。模块就是修复这些问题的,什么是模块?每个模块都有一个名字,它将相关代码组合在一起,是自包含的。模块中明确地描述了它需要的其他模块,以及自己对其他模块可见的部分。在这种方式下,模块之间的依赖是非常清晰的。我们有更强的封装性,这意味着我们可以隐藏内部的API,并且现在我们也遵循“Fail First”原则,因此当有模块缺失或者冲突的时候,你将得到一个错误。模块无处不在模块化的JDK允许JDK的开发者管理庞大复杂的自己。如果你在开发一个小而简单的应用,并不使用RMI、CORBA、JavaEE和其他的东西,那你为什么需要一个完整的、巨大而又重的Java运行环境呢?只使用包含你需要的模块的JDK,岂不是明智的。现在的模块化平台是这种情形成为可能。这是现在的JDK看起来的样子。在最底部是“java.base”模块,每一个其它的模块都显式或隐式地依赖于它。正如你看到的这样,依赖关系图是一个有向无环图,这意味着不允许出现循环依赖。模块依赖关系图下图基本上展示了模块是什么,每一个模块都有一个描述模块的文件,叫做“module-info.java”。什么是模块在文件“module-info.java”中你描述了模块的名字、运行需要的模块和其中对外可见的包。例如,你可以看到java.sql模块中对外暴露了哪些包和它需要哪些模块。java.sql因此简化一下,module-info.java 的内容看起来像下面这样子:module-info.java下面我们将介绍如何使用这些模块和创建自己的模块。How首先,你需要下载和安装JDK 9,你可以在找到它。Java Version$&java&-version
java&version&&9&Java(TM)&SE&Runtime&Environment&(build&9+181)
Java&HotSpot(TM)&64-Bit&Server&VM&(build&9+1下面我们在IntelliJ IDEA中构建一个项目:创建java项目下面介绍如何创建一个模块:创建模块创建模块之后,你需要在模块下的src下创建一个module-info.java文件:创建module-info.java我已经构建了一个项目包含两个模块:“com.rabbit”和“com.rabbit.log”,你可以看到项目的结构如下图:项目结构在模块 com.rabbit.log 中有两个类:InternalHello和Hello。InternalHello.javapackage&hello.log.public&class&InternalHello&{
&&&&public&static&String&sayHello(String&name){&&&&&&&&return&&Hello,&This&Greeting&is&internal&dear&&+&
}Hello.javapackage&hello.public&class&Hello&{
&&&&public&static&String&sayHello(String&name){&&&&&&&&return&&Hello,&&&+&
}在模块 com.rabbit.log 的modu-info.java中,写入如下所示:module&com.rabbit.log&{
&&&&exports&hello.
}这意味着package hello.log 在该模块外可见的,而package hello.log.internals是不可见的。RabbitMain是一个简单的JavaFX程序:package&com.import&hello.log.Himport&javafx.application.Aimport&javafx.scene.Simport&javafx.scene.control.Limport&javafx.scene.layout.StackPimport&javafx.stage.Spublic&class&RabbitMain&&extends&Application&{&&&&@Override
&&&&public&void&start(Stage&primaryStage)&throws&Exception&{
&&&&&&&&Label&label&=&new&Label(Hello.sayHello(&Hossein&));
&&&&&&&&StackPane&pane&=&new&StackPane();
&&&&&&&&pane.getChildren().add(label);
&&&&&&&&Scene&scene&=&new&Scene(pane);
&&&&&&&&primaryStage.setScene(scene);
&&&&&&&&primaryStage.show();
}这个模块看起来不需要暴露任何package,它需要 javafx.base 和 javafx.controls两个模块,为了使用Hello类还需要模块com.rabbit.log。因此模块 com.rabbit 的module-info.java看起来是下面这样子:module&com.rabbit&{&&&&requires&javafx.&&&&requires&javafx.&&&&requires&com.rabbit.
}当我们运行这个应用时,出现了如下的错误:Caused&by:&java.lang.IllegalAccessException:&class&com.sun.javafx.application.LauncherImpl&(in&module&javafx.graphics)&cannot&access&class&com.rabbit.RabbitMain&(in&module&com.rabbit)&because&module&com.rabbit&does&not&export&com.rabbit&to&module&javafx.graphics
&&&&at&java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
&&&&at&java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:589)这个错误很明显地告诉我们,需要将package com.rabbit暴露出去。意思是 javafx.graphics 是需要使用RabbitMain启动主窗口的,所以你需要暴露你的package给 javafx.graphics(主要:你可以暴露一个package给指定的模块而不是暴露给所有的模块)。因此,现在的 module-info.java 是下面的样子:module&com.rabbit&{&&&&requires&javafx.&&&&requires&javafx.&&&&requires&com.rabbit.&&&&exports&com.rabbit&to&javafx.
}在java 9中实现的javaFX看起来好像有bug(注意黄色的圈),下面就是我们的javaFX程序的运行结果:运行结果这个故事到这里并没有结束,关于模块以及它们之间的依赖关系的更加完整详细的介绍可以阅读书籍
。参考的。
若觉得本文不错,就分享一下吧!
评论加载中...
看过此文的用户,还看了以下文章
正在加载中
作者相关文章今年,2017年,我们将迎来 Java 语言的 22 岁生日,22岁,对于一个人而言,正是开始大展鸿图的年纪,可是对于日新月异的科技圈中的一门开发语言而言,却是一个傲视群雄的老态龙钟的年纪。
JVM 语言发展史
JVM 家族也是在这22年中茁壮发展,并且都秉承着 Java 的革命口号:一处编译,随处运行。那么,JVM 的带头人 Java 在 9.0 的版本中带来了什么变化呢?
今天介绍一个Java 9的功能,模块化(Modular);这可能使Java有史以来最大的Feature,它将自己长期依赖JRE的结构,转变成以Module为基础的组件,这感觉就像一个壮士,需要把自己的胳膊,腿等,一个个拆下来,并且还能够正常运行工作,难度可想而知。虽然,Java 9尚未发布,但这个功能让人期盼和煎熬了好多年了。从1995年的第一天起,Java带着一个口号,“Write once , Run anywhere” ,一路走来,从学院派的实验语言,变成开发者最青睐的语言,然后成为企业开发的统一语言,二十弱冠。时光如斯,Java也从一个创新的语言,慢慢变成一种“传统”,“老旧”,“经典”语言,同时也接受很多新鲜语言的挑战,例如Go,Scalar等。Java从来就不是一种完美的语言:GC的效率总是给高并发程序员带来不少痛苦和调整,Classpath地狱总是让很多错误诡异的发生,高级语言特性总是在JCP(Java Community Process)里面踢皮球而无法落地,异步模式的多线程编程总是有陡峭的学习曲线,Oracle JDK和OpenSDK总是有扯不清楚的关系,孤芳自傲且让人崩溃的J2EE框架。但是,我还是最喜欢Java编程语言,不仅因为使用了20年,更有两个原因:
Java的生态:几乎所有开发库都支持Java语言,Java是打开程序世界的钥匙。
Java语言的开源:Java源代码设计流畅,可以学到很多设计技能。
模块化从Java 7就开始计划推出 ,但由于其过于复杂,不断跳票 Java 7和Java 8,终于计划在Java 9中推出,我们一起拭目以待吧! 目前,Java 9的功能基本开发完毕,剩下半年的时间,解决各种Bug。下面是Java 9的时间表!
Java 9的时间表
Java 9中最重要的功能,毫无疑问就是模块化(Module),代码名字叫做Jigsaw(拉锯),这个拉锯项目拉了几年,终于要把庞大冗余的Java锯成一个个的Module,方便开发和部署。熟悉Java的同学,都知道JRE有一个超级大rt.jar(例如,Java 8的rt.jar中有65M),运行一个hello world,你也需要一个数百兆的JRE环境,如果在J2EE环境,情况将变得复杂无比。另外,如果你没有深受Classpath Hell所害,说明你还不是一个深度Java程序员。
Java 9 模块化优势对比图
模块化的功能有几个目的:
让Java的SE程序更加容易轻量级部署
改进组件间的依赖管理,引入比Jar粒度更大的Module
改进性能和安全性
如果用更加简单解释,那就是“解决Classpath地狱问题,改进部署能力”。Module的内容比较多,为了由浅入深,我按照一些问题和我的理解来介绍模块化。
1.什么是Java Module(模块)
模块就是代码和数据的封装体,代码是指一些包括类型的Packages。Package是一些类路径名字的约定,而模块是一个或多个Packages组成的一个封装体。
什么是模块化
2. 模块的代码例子
模块的是通过module-info.java进行定义,编译后打包后,就成为一个模块的实体;在模块的定义文件中,我们需要指定模块之间的依赖靠关系,可以exports给那些模块用,需要使用那些模块(requires) 。下面是一个例子:
module com.foo.bar {
requires org.baz.
exportscom.foo.bar.
exportscom.foo.bar.
META-INF/MANIFEST.MF
module-info.class
com/foo/bar/alpha/AlphaFactory.class
com/foo/bar/alpha/Alpha.class
3.JDK8 和JDK9有什么不一样?
JDK8的JRE的部署是一个单体模式,一个超大的rt.jar(大约60多兆),tools.jar也有几十兆,即使使用一个Hello Worlds,你也需要一整套上百兆的JRE环境。JAVA 9 引入模块后,将所有的类组织成模块形式,模块之间有着优美的依赖关系(至少现在很整齐,不知道过几个版本会不会继续保持优雅)。
Java 8的包之间的依赖关系
Java9的依赖关系(模块之间依赖关系)
4. public关键字不再意味着Accessible(可访问了)
模块之间的关系被称作readability(可读性),代表一个模块是否可以找到这个模块文件,并且读入系统中(注意:并非代表可以访问其中的类型)。在实际的代码,一个类型对于另外一个类型的调用,我们称之为可访问性(Accessible),这意味着可以使用这个类型; 可访问性的前提是可读性,换句话说,现有模块可读,然后再进一步检测可访问性(安全)。在Java 9中, Public不再意味着任意的可访问性!
public关键字不再意味着任意的可访问性
模块之间的关联关系
5.什么是模块的Transitive 引用(间接引用)
举个例子:
因此标记了transitive可以可以提供一个间接可读性。在myapp中,可以直接引用Logger类了。
可读性示意图
6. Module 和Maven是什么关系
看完Module,这么详细的表达依赖关系,是不是和什么软件很相似?是不是想起了Maven还是Gradle? 仔细想象,Modular和它们还是不一样的。
Modular是系统内置用于表述组件之间的关系,对于版本的管理还是处于最原始的状体。它管理一种强制的依赖关系。Maven有两个核心功能 a) 组件的依赖管理,特别是版本的管理,这种依赖是逻辑上的,并非强制的 b)管理开发过程中的各种任务,初始化,测试等等。
7. JLink介绍
JLink是将Module进行打包的工具,帮助目标机器的部署。打包后的文件将非常精简。
jLink工作示意图
jLink工作指令示范
8 Module的原理和实现
在内部实现中,整个过程非常繁琐复杂,大概有几件事情;
a)将系统内部类进行模块化
这样不用在区分太多J2ME, J2SE,J2EE了,大家都是用模块作为沟通语言。这需要整理所有的类和它们调用关系,调用频次等,把系统类模块化,这可能最复杂的一部分,不过结果是完美的。
b) 将ClassLoader分级
将ClassLoader分为三个级别,Bootstrap Loader具有最高优先级和权限,主要是核心的系统类;Platform Loader用于扩展的一些系统类,例如SQL,XML等;Application Loader主要用于应用程序的Loader。在这三个级别的Loader下面有一个统一Module 管理,用于控制和管理模块间的依赖关系,可读性,可访问性等。 注意,ClassLoader在Java 9中的类装载逻辑和之前一样,但是,通过模块管理系统,ClassLoader.FindClass的能力,将被限制在readable&accessible的条件下,而不是之前的简单的Public条件。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!标签:至少1个,最多5个
本文档提供了几个简单的例子,让开发人员开始使用模块。
例子中的文件路径使用斜杠,路径分隔符是冒号。使用微软Windows开发的人员应该使用文件路径以反斜杠和一个分号作为路径分隔符。
第一个例子是一个只打印“Greetings!”命名为com.greetings的模块。该模块包括两个源文件:模块声明文件(module-info.java)和Main.java
按惯例,模块的源代码在一个目录中,该目录是模块的名称:
src/com.greetings/com/greetings/Main.java
src/com.greetings/module-info.java
$ cat src/com.greetings/module-info.java
module com.greetings { }
$ cat src/com.greetings/com/greetings/Main.java
package com.
public class Main {
public static void main(String[] args) {
System.out.println("Greetings!");
使用以下命令,将源码编译到 mods/com.greetings 目录下:
$ mkdir -p mods/com.greetings
$ javac -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java
现在我们用下面的命令运行这个例子:
$ java -modulepath mods -m com.greetings/com.greetings.Main
-modulepath是模块的路径,它的值是一个或多个包含模块的目录。-m 选项指定了主模块,在/后的值是模块主类包含包名的完整名称。
Greetings world
第二个示例是在之前示例的基础上增加了org.astro模块依赖,模块org.astro提供org.astro包的API。
src/org.astro/module-info.java
src/org.astro/org/astro/World.java
src/com.greetings/com/greetings/Main.java
src/com.greetings/module-info.java
$ cat src/org.astro/module-info.java
module org.astro {
exports org.
$ cat src/org.astro/org/astro/World.java
package org.
public class World {
public static String name() {
return "world";
$ cat src/com.greetings/module-info.java
module com.greetings {
requires org.
$ cat src/com.greetings/com/greetings/Main.java
package com.
import org.astro.W
public class Main {
public static void main(String[] args) {
System.out.format("Greetings %s!%n", World.name());
该模块编译,在同一时间。使用javac命令指定模块路径编译模块com.greetings,并有模块org.astro的引用,这样可以获取到org.astro提供的API。
$ mkdir mods/org.astro mods/com.greetings
$ javac -d mods/org.astro src/org.astro/module-info.java src/org.astro/org/astro/World.java
$ javac -modulepath mods -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java
该示例以与第一个示例完全相同的方式运行:
$ java -modulepath mods -m com.greetings/com.greetings.Main
Greetings world!
多模块编译
在前面的示例,模块 com.greetings 和模块 org.astro 是分别编译的。使用javac 命令编译模块时还可以一次编译多个模块。
$ mkdir mods
$ javac -d mods -modulesourcepath src $(find src -name "*.java")
$ find mods -type f
mods/com.greetings/com/greetings/Main.class
mods/com.greetings/module-info.class
mods/org.astro/module-info.class
mods/org.astro/org/astro/World.class
到目前为止的示例中,已编译的模块的内容在文件系统上以分散的文件的形式存储。当用于分发和部署时通常更方便的方式是将一个模块打包成一个模块化的JAR。一个模块化的JAR是一个普通的jar文件中在顶级目录有一个module-info.class。下面的示例在mlib目录org.astro@1.0.jar和com.greetings.jar。
$ mkdir mlib
$ jar --create --file=mlib/org.astro@1.0.jar --module-version=1.0 -C mods/org.astro .
$ jar --create --file=mlib/com.greetings.jar --main-class=com.greetings.Main -C mods/com.greetings .
com.greetings.jar
org.astro@1.0.jar
在这个例子中,org.astro模块打包时表明了它的版本是1.0 (--module-version=1.0)。模块com.greetings在打包时表明其主类是com.greetings.Main (--main-class=com.greetings.Main)。我们现在可以执行模块com.greetings而无需指定其主类:
$ java -mp mlib -m com.greetings
Greetings world!
上面的命令中使用了 -modulepath 的简写 -mp 。
jar工具增加了很多新的选项(可以通过jar -help查看),其中之一是打印一个模块jar的模块声明:
原文中给出的是:
$ jar --print-module-descriptor --file=mlib/org.astro@1.0.jar
org.astro@1.0
java.base [ MANDATED ]
但我实际在Windows下测试的结果为:
C:\Users\coderknock\workspace\JDK9&jar --print-module-descriptor --file=mlib\org.astro@1.0.jar
org.astro@1.0
requires mandated java.base
exports org.astro
C:\Users\coderknock\workspace\JDK9&jar --print-module-descriptor --file=mlib\com.greetings.jar
com.greetings
requires mandated java.base
requires org.astro
conceals com.greetings
main-class com.greetings.Main
缺少requires(依赖) 或者exports(输出)
如果我们在上一个示例中在com.greetings module的模块声明中没有设定依赖org.astro,让我们看看会发生什么:
$ cat src/com.greetings/module-info.java
module com.greetings {
// requires org.
$ javac -modulepath mods -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java src/com.greetings/com/greetings/Main.java:2: 错误: 程序包org.astro不存在
import org.astro.W
src/com.greetings/com/greetings/Main.java:5: 错误: 找不到符号
System.out.format("Greetings %s!%n", World.name());
变量 World
位置: 类 Main
现在我们试一下,com.greetings声明了依赖,但是org.astro没有声明输出会发生什么:
$ cat src/com.greetings/module-info.java
module com.greetings {
requires org.
$ cat src/org.astro/module-info.java
module org.astro {
// exports org.
$ javac -modulepath mods -d mods/com.greetings src/com.greetings/module-info.java src/com.greetings/com/greetings/Main.java src/com.greetings/com/greetings/Main.java:2: 错误: 程序包org.astro不存在
import org.astro.W
src/com.greetings/com/greetings/Main.java:5: 错误: 找不到符号
System.out.format("Greetings %s!%n", World.name());
变量 World
位置: 类 Main
服务允许服务消费者模块和服务提供商模块之间的松散耦合。
这个例子有一个服务消费模块和一个服务提供模块:
模块com.socket输出了一个网络套接字的API。API被封装在com.socket包,所以这个包是输出者。API是可插拔的,允许替换具体的实现。com.socket.spi.networksocketprovider是实际提供服务的抽象类,所以com.socket.spi也应该被输出。
org.fastsocket模块是一个服务提供模块,它提供了一个com.socket.spi.NetworkSocketProvider的实现,不需要输出。
下面是 com.socket 模块的源码:
$ cat src/com.socket/module-info.java
module com.socket {
exports com.
exports com.socket.
uses com.socket.spi.NetworkSocketP
$ cat src/com.socket/com/socket/NetworkSocket.java
package com.
import java.io.C
import java.util.I
import java.util.ServiceL
import com.socket.spi.NetworkSocketP
public abstract class NetworkSocket implements Closeable {
protected NetworkSocket() { }
public static NetworkSocket open() {
ServiceLoader&NetworkSocketProvider& sl
= ServiceLoader.load(NetworkSocketProvider.class);
Iterator&NetworkSocketProvider& iter = sl.iterator();
if (!iter.hasNext())
throw new RuntimeException("No service providers found!");
NetworkSocketProvider provider = iter.next();
return provider.openNetworkSocket();
$ cat src/com.socket/com/socket/spi/NetworkSocketProvider.java
package com.socket.
import com.socket.NetworkS
public abstract class NetworkSocketProvider {
protected NetworkSocketProvider() { }
public abstract NetworkSocket openNetworkSocket();
下面是org.fastsocket模块的源码:
$ cat src/org.fastsocket/module-info.java
module org.fastsocket {
requires com.
provides com.socket.spi.NetworkSocketProvider
with org.fastsocket.FastNetworkSocketP
$ cat src/org.fastsocket/org/fastsocket/FastNetworkSocketProvider.java
package org.
import com.socket.NetworkS
import com.socket.spi.NetworkSocketP
public class FastNetworkSocketProvider extends NetworkSocketProvider {
public FastNetworkSocketProvider() { }
public NetworkSocket openNetworkSocket() {
return new FastNetworkSocket();
$ cat src/org.fastsocket/org/fastsocket/FastNetworkSocket.java
package org.
import com.socket.NetworkS
class FastNetworkSocket extends NetworkSocket {
FastNetworkSocket() { }
public void close() { }
为了简单起见,我们一起编译这两个模块。在实践中,服务消费模块和服务提供模块几乎总是单独编译。
$ mkdir mods
$ javac -d mods -modulesourcepath src $(find src -name "*.java")
最后我们修改一下com.greetings模块,在其Main中使用上面提供出的API:
$ cat src/com.greetings/module-info.java
module com.greetings {
requires com.
$ cat src/com.greetings/com/greetings/Main.java
package com.
import com.socket.NetworkS
public class Main {
public static void main(String[] args) {
NetworkSocket s = NetworkSocket.open();
System.out.println(s.getClass());
$ javac -d mods/com.greetings/ -mp mods $(find src/com.greetings/ -name "*.java")
最后,我们运行一下:
$ java -mp mods -m com.greetings/com.greetings.Main
class org.fastsocket.FastNetworkSocket
输出结果表明服务提供者已经找到,而且使用的是NetworkSocket工厂,实现是FastNetworkSocketProvider。
jlink 是连接器工具,用来连接一组模块 ,连同他们的依赖关系,创建一个自定义模块运行时镜像( JEP 220规范定义)。
该工具目前需要的封装成模块JAR或者JMOD格式的模块的路径。JDK中将一些标准以及JDK特性包装成JMOD格式(在JDK安装目录的jmods目录下)。
下面的示例创建一个运行时镜像包含模块com.greetings以及传递相关的依赖:
jlink --modulepath $JAVA_HOME/jmods:mlib --addmods com.greetings --output greetingsapp
--modulepath 是包含将要打包的模块的模块路径(示例中$JAVA_HOME/jmods是JDK内置的模块,所有模块默认引入有java.base模块的依赖,java.base在$JAVA_HOME/jmods中),Linux目录分隔符是:Windows是;按照自己的环境修改“jmods:mlib”的符号。(我在本地测试这个没有成功,有成功的同学请留言)
$JAVA_HOME/jmods是java.base.jmod的模块路径同时包含别的JDK模块.。如果你是自己编译的OpenJDK,那么应该使用 $BUILDOUTPUT/images/jmods,
$BUILDOUTPUT 指的是你设置的编译输出目录。
在模块路径设置里的目录mlib包含模块com.greetings。
jlink工具支持许多高级选项自定义生成的镜像, jlink --help查看更多选项。
本人的直播课程在 7 月份就要开始了,希望小伙伴们支持一下,现在报名有优惠噢
6 收藏&&|&&17
你可能感兴趣的文章
你可能感兴趣的文章
分享到微博?
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。

我要回帖

更多关于 jlink java9 的文章

 

随机推荐