java 9 功能的新特性 (一)模块化

Oracle 在 9月22 日终于发布了 jdk 9 (难产了好长时间啊%>_<%),java在走过了22个年头之后迎来了新的版本,作为一门使用率排在第一的编程语言(截止到现在10月份), What 's new ?? 话不多说,让我们看一下这次发布带给我们的一个主要新功能——模块化。

Jigsaw

Modularity(模块化)是第一个要介绍的,代码名称为Jigsaw。作为这次发布的重点功能,也是本文详细介绍的。其实在jdk 7的时候Oracle就考虑引入了,但是这中间考虑到稳定性、安全性等问题直到 jdk 9 才引入。
首先介绍一下模块化概念:

简单说模块是代码和数据的封装体。这里的代码指的是一些包含类型的Packages 。Packages是类路径名称,模块就是一个或者多个Package组成的封装体。

说完了概念,那么为什么Oracle要抛出这样一个概念呢?

  • 改进组件间的依赖管理,引入比Jar粒度更大的Module
  • 使得java SE程序更加容易轻量部署
  • 改进性能和安全性

先说第二点如何理解,请看下面这张图:

image.png

运行一个简单的hello world程序,在JDK8中你需要几百兆的JRE环境,有些jar可能并不是你运行程序所必须的,浪费了很多空间。但是在 JDK 9中,JDK被分成了大约94个modules,在用的时候引入你需要的module就行了。

对于第一点如何理解呢?其实这点说的是解决 java 中 ““classpath hell”” 或者说“jar hell”的问题。看到这两个名词我也是一脸懵逼啊?!what the hell !

PS: ““classpath hell”” 和“jar hell”在本质上相同,只是后者更加关注由复杂类加载层级产生的问题。

image.png

JAR Hell

JAR Hell 问题源自java中的类加载机制。它主要表现出四个问题:
1、无法表述的依赖关系(Unexpressed Dependencies)和传递依赖(Transitive Dependencies)
首先一个 jar 包是不能通过某种方式去告诉JVM 我依赖哪些其他 jar包的。 需要开发者自己通过读文档,判断依赖关系,下载缺失的依赖jar包。而且只有在运行时需要用到依赖jar包时,才会报 NoClassDefFoundError的错误。传递依赖指的是应用程序需要依赖一些库,而这些库又会依赖其他一些库,像这样依赖传递下去,使得依赖关系呈现指数级复杂关系,很容易出错。
2、遮蔽(Shadowing)
不同的jar包在类路径上的类有完全相同的名字。这种现象比较常见,原因有很多,比如相同库中有两个不同版本,库被重命名并添加到类路径中两次。
由于类在第一个包含他们的JAR包中就已经被加载,类中的变量会“shadow” 所有其他变量,使得他们不能在用了。
是不是说的比较晦涩?show me the code!!!

public class Base {
    public  String name = "Base";
    public  String getName() { return name; }
}


public class Sub extends Base {
    public String name = "Sub";
    public String getName() { return name; }
}

下面程序输出的是“Sub”, 子类shadow 父类的变量,是不是立马理解了?

class Program {
  public static void main(String[] args) {
    Sub s = new Sub();
    System.out.println(s.name); //Output "Sub"
  }
}

3、版本冲突(Version Conflicts)
当两个库依赖的的第三方库是不同并且不兼容的时候就会出现版本问题。如果两个版本同时出现在类路径中,会出现不可预知的结果。首先因为“shadowing”,在这两个版本中存在的类只会加载一个。更糟糕的是,如果一个类存在于一个库而不在另一个中,这个类被访问的时候也会被加载进来,调用库的代码会发现两个版本混在一起。但是不兼容版本是必须的,缺少一个程序就无法正常运行,比如抛出NoClassDefFoundErrors
4、复杂的类加载(Complex Class Loading)
默认情况下所有程序类都是被相同的类加载器加载的,但是开发人员可以自己定义类加载器。类加载通常对开发者来说是不可见的,由容器比如web服务、组件系统来完成,但是
all abstractions are leaky。开发人员在某些情况下得自己显示地加载类,这些自定义的类加载器会导致复杂的不可预知的行为。(原谅我直接这句话直接翻译了%>_<%)。

那么Module是如何处理上述四个问题的呢?

首先看一下JDK 9如何定义一个module:
模块的是通过module-info.java进行定义,编译后打包后,就成为一个模块的实体;在模块的定义文件中,我们需要指定模块之间的依赖靠关系,可以exports给那些模块用,需要使用那些模块(requires) 。下面是一个例子:

module com.foo.bar {
requires org.baz.qux;
exports com.foo.bar.alpha;
exports com.foo.bar.beta;
}

1、对于第一个问题,先看下图,左边是定义module的代码,app需要zoop和sql,右边是依赖关系。

image.png

JVM会通过了module path 去解析所有的依赖,类似下面的图

image.png

,这个过程发生在启动阶段,而不是运行阶段。当不是所有的modules在这条路径上被发现时,解析一个module传递依赖的过程就失败了。这就解决了无法描述和无限传递依赖的问题。
2、第二问题。模块系统只要发现两个模块输出相同的包给同一个模块就会报错。如下图所示。

image.png

3、版本冲突问题,最直接的解决方式是模块系统能加载相同模块的不同版本,并且保证这些版本不会互相影响,保证封装性和可读性。但是抱歉,版本冲突问题目前没有办法解决。原因摘自官网:

It is not necessary to support more than one version of a module within a single configuration.
事实上,现在的Maven和Gradle也没法理解module的版本信息。

4、最后是复杂的类加载问题,先说结果:Module并没有彻彻底底解决该问题,但是简化了问题复杂性。
Oracle引入了层(Layer)的概念。(一个module够烦的,还抛出个layer概念,发现很多互联网公司都喜欢抛个新概念出来强行装逼啊!!!!!TMD)。layer控制模块和类加载器之间的关系。使得在同一个layer里的不同模块都使用相同的类加载器。换句话说类加载器和模块之间是1:n的关系。同时Layer还有堆叠的特点,如下图所示。

image.png

一个新layer可以在boot layer上构建,另外的layer也能在这个layer上构建。在解析某个layer里的module时候可以读取里面的modules或者在它下面的layer里的module。

说白了,我的个人理解,layer就是让一个类加载器去专门负责某个module下的所有类加载,有什么好处,我也不知道啊?各位能不能写个列子出来???

讲了模块化的好处,似乎还是比较抽象,下面两张图比较直观展示模块化之后的好处:
下是 jdk 8中包的依赖关系

image.png

是不是很复杂呢?

JAVA 9 引入模块后,将所有的类组织成模块形式,模块之间有着优美的依赖关系
再看JDK9 简化后的关系图

image.png

最后的问题

以下是Jigsaw官网的原话:

Make it easier for developers to construct and maintain libraries and large applications, for both the Java SE and EE Platforms.

是不是让你联想到了MavenGradle? 他们之间到底是什么关系啊??

image.png

Google 一下在StackOverFlow上找到了答案。

在Jigsaw之后,public 关键字不再意味着任意的可访问性。访问的范围局限在JAR,想要访问 JAR包外的其他类,必须export。 任何模块之间的交互必须通过module-info文件来定义。
举个列子,生成的WAR包可能并没改变源代码,但是在其中的所有JAR必须定义module-info。
Maven 有两个主要的特征。他负责项目的依赖管理和构建。依赖管理的意思是Maven可以决定库中的版本并从仓库中下载下来。构建的意思是Maven可以编译代码并且打包成产品。

Module是系统内置用于表述组件之间的关系,对于版本的管理还是处于最原始的状体。它管理一种强制的依赖关系。

总结一下:Maven还是组要负责构建,包括开发过程中的各种任务,初始化,测试。但是要利用Jigsaw, Maven必须知道如何通过Jigsaw模块编译打包。Modules 对于像Maven这样的构建工具(build tools)来说扮演的是辅助补充的角色。因为这些构建工具在构建时建立的依赖关系图谱和他们版本可以根据Module来创建,Module强制确定了module和artifacts之间的依赖关系,而Maven对于依赖并非是强制的。

本文主要参考了一下两个国外文献,一篇CSDN上的博客,以及oracle官方的视频讲解,youtube上有的(别问我怎么翻墙)
https://dzone.com/articles/what-is-jar-hell
https://blog.codefx.org/java/dev/will-there-be-module-hell/#Shadowing
http://www.cnblogs.com/xiongxx/p/6734416.html


感谢阅读,这是我第一次在简书上写文章,以后会多写一些,有问题欢迎讨论,最后祝大家节日快乐!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 看着一排排书架上的书,随意挑出一本,之后随意的翻翻,然后快速放回去。再取下一本,同样就那么翻翻,而后放回去。但其中...
    一瓶水阅读 354评论 0 2
  • 一直以来都很喜欢文字,但大部分的灵感都只存在于一瞬间,仅仅就停留在一种感觉上,却从未真正记录下来。长此以往,喜欢的...
    朱墨点绛唇阅读 251评论 0 0
  • 带孩子去张家界玩了三天,亲子共读记录也断了几天。倒不是没时间写,而是到了酒店孩子就拿我手机听西游记,手机代替牛听听...
    洁儿_42cb阅读 191评论 0 1
  • 每天都有人在重新开始, 我觉得今天是个好日子, 所以就从今天开始吧, 读书,运动,尝试, 一切听起来都很美好。
    Young3yang阅读 205评论 0 0