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

Oracle 在 9月22 日終于發(fā)布了 jdk 9 (難產(chǎn)了好長時間啊%>_<%),java在走過了22個年頭之后迎來了新的版本祖驱,作為一門使用率排在第一的編程語言(截止到現(xiàn)在10月份)乱顾, What 's new ?? 話不多說,讓我們看一下這次發(fā)布帶給我們的一個主要新功能——模塊化。

Jigsaw

Modularity(模塊化)是第一個要介紹的乞巧,代碼名稱為Jigsaw。作為這次發(fā)布的重點功能摊鸡,也是本文詳細(xì)介紹的绽媒。其實在jdk 7的時候Oracle就考慮引入了,但是這中間考慮到穩(wěn)定性免猾、安全性等問題直到 jdk 9 才引入巩那。
首先介紹一下模塊化概念:

簡單說模塊是代碼和數(shù)據(jù)的封裝體琅轧。這里的代碼指的是一些包含類型的Packages 僵缺。Packages是類路徑名稱寸五,模塊就是一個或者多個Package組成的封裝體。

說完了概念锨苏,那么為什么Oracle要拋出這樣一個概念呢石窑?

  • 改進(jìn)組件間的依賴管理,引入比Jar粒度更大的Module
  • 使得java SE程序更加容易輕量部署
  • 改進(jìn)性能和安全性

先說第二點如何理解蚓炬,請看下面這張圖:

image.png

運行一個簡單的hello world程序松逊,在JDK8中你需要幾百兆的JRE環(huán)境,有些jar可能并不是你運行程序所必須的肯夏,浪費了很多空間经宏。但是在 JDK 9中,JDK被分成了大約94個modules驯击,在用的時候引入你需要的module就行了烁兰。

對于第一點如何理解呢?其實這點說的是解決 java 中 ““classpath hell”” 或者說“jar hell”的問題徊都』φ澹看到這兩個名詞我也是一臉懵逼啊暇矫?主之!what the hell !

PS: ““classpath hell”” 和“jar hell”在本質(zhì)上相同,只是后者更加關(guān)注由復(fù)雜類加載層級產(chǎn)生的問題李根。

image.png

JAR Hell

JAR Hell 問題源自java中的類加載機制槽奕。它主要表現(xiàn)出四個問題:
1、無法表述的依賴關(guān)系(Unexpressed Dependencies)和傳遞依賴(Transitive Dependencies)
首先一個 jar 包是不能通過某種方式去告訴JVM 我依賴哪些其他 jar包的房轿。 需要開發(fā)者自己通過讀文檔粤攒,判斷依賴關(guān)系所森,下載缺失的依賴jar包。而且只有在運行時需要用到依賴jar包時夯接,才會報 NoClassDefFoundError的錯誤焕济。傳遞依賴指的是應(yīng)用程序需要依賴一些庫,而這些庫又會依賴其他一些庫盔几,像這樣依賴傳遞下去晴弃,使得依賴關(guān)系呈現(xiàn)指數(shù)級復(fù)雜關(guān)系,很容易出錯问欠。
2、遮蔽(Shadowing)
不同的jar包在類路徑上的類有完全相同的名字粒蜈。這種現(xiàn)象比較常見顺献,原因有很多,比如相同庫中有兩個不同版本枯怖,庫被重命名并添加到類路徑中兩次注整。
由于類在第一個包含他們的JAR包中就已經(jīng)被加載,類中的變量會“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)
當(dāng)兩個庫依賴的的第三方庫是不同并且不兼容的時候就會出現(xiàn)版本問題藻茂。如果兩個版本同時出現(xiàn)在類路徑中驹暑,會出現(xiàn)不可預(yù)知的結(jié)果。首先因為“shadowing”辨赐,在這兩個版本中存在的類只會加載一個优俘。更糟糕的是,如果一個類存在于一個庫而不在另一個中掀序,這個類被訪問的時候也會被加載進(jìn)來帆焕,調(diào)用庫的代碼會發(fā)現(xiàn)兩個版本混在一起。但是不兼容版本是必須的不恭,缺少一個程序就無法正常運行叶雹,比如拋出NoClassDefFoundErrors
4换吧、復(fù)雜的類加載(Complex Class Loading)
默認(rèn)情況下所有程序類都是被相同的類加載器加載的浑娜,但是開發(fā)人員可以自己定義類加載器。類加載通常對開發(fā)者來說是不可見的式散,由容器比如web服務(wù)筋遭、組件系統(tǒng)來完成,但是
all abstractions are leaky。開發(fā)人員在某些情況下得自己顯示地加載類漓滔,這些自定義的類加載器會導(dǎo)致復(fù)雜的不可預(yù)知的行為编饺。(原諒我直接這句話直接翻譯了%>_<%)。

那么Module是如何處理上述四個問題的呢响驴?

首先看一下JDK 9如何定義一個module:
模塊的是通過module-info.java進(jìn)行定義透且,編譯后打包后,就成為一個模塊的實體豁鲤;在模塊的定義文件中秽誊,我們需要指定模塊之間的依賴靠關(guān)系,可以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炫狱,右邊是依賴關(guān)系藻懒。

image.png

JVM會通過了module path 去解析所有的依賴,類似下面的圖

image.png

视译,這個過程發(fā)生在啟動階段嬉荆,而不是運行階段。當(dāng)不是所有的modules在這條路徑上被發(fā)現(xiàn)時酷含,解析一個module傳遞依賴的過程就失敗了员寇。這就解決了無法描述和無限傳遞依賴的問題。
2第美、第二問題蝶锋。模塊系統(tǒng)只要發(fā)現(xiàn)兩個模塊輸出相同的包給同一個模塊就會報錯。如下圖所示什往。

image.png

3扳缕、版本沖突問題,最直接的解決方式是模塊系統(tǒng)能加載相同模塊的不同版本别威,并且保證這些版本不會互相影響躯舔,保證封裝性和可讀性。但是抱歉省古,版本沖突問題目前沒有辦法解決粥庄。原因摘自官網(wǎng):

It is not necessary to support more than one version of a module within a single configuration.
事實上,現(xiàn)在的Maven和Gradle也沒法理解module的版本信息豺妓。

4惜互、最后是復(fù)雜的類加載問題布讹,先說結(jié)果:Module并沒有徹徹底底解決該問題,但是簡化了問題復(fù)雜性训堆。
Oracle引入了層(Layer)的概念描验。(一個module夠煩的,還拋出個layer概念坑鱼,發(fā)現(xiàn)很多互聯(lián)網(wǎng)公司都喜歡拋個新概念出來強行裝逼氨炝鳌!B沉ぁ:艄伞!画恰!TMD)彭谁。layer控制模塊和類加載器之間的關(guān)系。使得在同一個layer里的不同模塊都使用相同的類加載器阐枣。換句話說類加載器和模塊之間是1:n的關(guān)系马靠。同時Layer還有堆疊的特點奄抽,如下圖所示蔼两。

image.png

一個新layer可以在boot layer上構(gòu)建,另外的layer也能在這個layer上構(gòu)建逞度。在解析某個layer里的module時候可以讀取里面的modules或者在它下面的layer里的module额划。

說白了,我的個人理解档泽,layer就是讓一個類加載器去專門負(fù)責(zé)某個module下的所有類加載俊戳,有什么好處,我也不知道肮菽洹抑胎?各位能不能寫個列子出來?渐北?阿逃?

講了模塊化的好處,似乎還是比較抽象赃蛛,下面兩張圖比較直觀展示模塊化之后的好處:
下是 jdk 8中包的依賴關(guān)系

image.png

是不是很復(fù)雜呢恃锉?

JAVA 9 引入模塊后,將所有的類組織成模塊形式呕臂,模塊之間有著優(yōu)美的依賴關(guān)系
再看JDK9 簡化后的關(guān)系圖

image.png

最后的問題

以下是Jigsaw官網(wǎng)的原話:

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

是不是讓你聯(lián)想到了MavenGradle? 他們之間到底是什么關(guān)系捌仆小?歧蒋?

image.png

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

在Jigsaw之后州既,public 關(guān)鍵字不再意味著任意的可訪問性。訪問的范圍局限在JAR瘟芝,想要訪問 JAR包外的其他類易桃,必須export。 任何模塊之間的交互必須通過module-info文件來定義锌俱。
舉個列子晤郑,生成的WAR包可能并沒改變源代碼,但是在其中的所有JAR必須定義module-info贸宏。
Maven 有兩個主要的特征造寝。他負(fù)責(zé)項目的依賴管理和構(gòu)建。依賴管理的意思是Maven可以決定庫中的版本并從倉庫中下載下來吭练。構(gòu)建的意思是Maven可以編譯代碼并且打包成產(chǎn)品诫龙。

Module是系統(tǒng)內(nèi)置用于表述組件之間的關(guān)系,對于版本的管理還是處于最原始的狀體鲫咽。它管理一種強制的依賴關(guān)系签赃。

總結(jié)一下:Maven還是組要負(fù)責(zé)構(gòu)建,包括開發(fā)過程中的各種任務(wù)分尸,初始化锦聊,測試。但是要利用Jigsaw, Maven必須知道如何通過Jigsaw模塊編譯打包箩绍。Modules 對于像Maven這樣的構(gòu)建工具(build tools)來說扮演的是輔助補充的角色孔庭。因為這些構(gòu)建工具在構(gòu)建時建立的依賴關(guān)系圖譜和他們版本可以根據(jù)Module來創(chuàng)建,Module強制確定了module和artifacts之間的依賴關(guān)系材蛛,而Maven對于依賴并非是強制的圆到。

本文主要參考了一下兩個國外文獻(xiàn),一篇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


感謝閱讀,這是我第一次在簡書上寫文章豆赏,以后會多寫一些挣菲,有問題歡迎討論,最后祝大家節(jié)日快樂:诱馈己单!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市耙饰,隨后出現(xiàn)的幾起案子纹笼,更是在濱河造成了極大的恐慌,老刑警劉巖苟跪,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廷痘,死亡現(xiàn)場離奇詭異蔓涧,居然都是意外死亡,警方通過查閱死者的電腦和手機笋额,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門元暴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兄猩,你說我怎么就攤上這事茉盏。” “怎么了枢冤?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵鸠姨,是天一觀的道長。 經(jīng)常有香客問我淹真,道長讶迁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任核蘸,我火速辦了婚禮巍糯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘客扎。我一直安慰自己祟峦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布虐唠。 她就那樣靜靜地躺著搀愧,像睡著了一般惰聂。 火紅的嫁衣襯著肌膚如雪疆偿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天搓幌,我揣著相機與錄音杆故,去河邊找鬼。 笑死溉愁,一個胖子當(dāng)著我的面吹牛处铛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拐揭,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼撤蟆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了堂污?” 一聲冷哼從身側(cè)響起家肯,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盟猖,沒想到半個月后讨衣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體换棚,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年反镇,在試婚紗的時候發(fā)現(xiàn)自己被綠了固蚤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡歹茶,死狀恐怖夕玩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惊豺,我是刑警寧澤风秤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站扮叨,受9級特大地震影響缤弦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜彻磁,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一碍沐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衷蜓,春花似錦累提、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至置吓,卻和暖如春无虚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衍锚。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工友题, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人戴质。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓度宦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親告匠。 傳聞我的和親對象是個殘疾皇子戈抄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 看著一排排書架上的書,隨意挑出一本后专,之后隨意的翻翻划鸽,然后快速放回去。再取下一本行贪,同樣就那么翻翻漾稀,而后放回去模闲。但其中...
    一瓶水閱讀 380評論 0 2
  • 一直以來都很喜歡文字,但大部分的靈感都只存在于一瞬間崭捍,僅僅就停留在一種感覺上尸折,卻從未真正記錄下來。長此以往殷蛇,喜歡的...
    朱墨點絳唇閱讀 258評論 0 0
  • 帶孩子去張家界玩了三天实夹,親子共讀記錄也斷了幾天。倒不是沒時間寫粒梦,而是到了酒店孩子就拿我手機聽西游記亮航,手機代替牛聽聽...
    潔兒_42cb閱讀 202評論 0 1
  • 每天都有人在重新開始, 我覺得今天是個好日子匀们, 所以就從今天開始吧缴淋, 讀書,運動泄朴,嘗試重抖, 一切聽起來都很美好。
    Young3yang閱讀 235評論 0 0