Java 9終於要包含Jigsaw項目了

當Jigsaw在Java 9中最終發佈時,這個項目的歷史已經超過八年了。html

 

轉載於:http://www.itxuexiwang.com/a/liunxjishu/2016/0228/180.html?1456925937java

在最初的幾年中,它必需要與另外兩個相似的Java規範請求( Java Specification Request )進行競爭,這兩個規範名爲JSR 277 Java模塊系統(Java Module System)以及JSR 294 加強的模塊化支持(Improved Modularity Support)。它還致使了與OSGi社區的衝突,人們擔憂Jigsaw項目會成爲沒必要要且不完備的功能性重複,逼迫Java開發人員必須在兩種互不兼容的模塊系統中作出選擇。

 

 

在早期,這個項目並無充足的人手,在2010年Sun併入Oracle的時候,甚至一度中斷。直到2011年,在Java中須要模塊系統的強烈需求被重申,這項工做才獲得徹底恢復。linux

接下來的三年是一個探索的階段,結束於2014年的7月,當時創建了多項Java加強提議( Java Enhancement Proposal),包括JEP 200 模塊化JDK(Modular JDK)、JEP 201 模塊化源碼(Modular Source Code)和JEP 220 模塊化運行時鏡像(Modular Run-Time Image),以及最終的JSR 376 Java平臺模塊系統(Java Platform Module System)。上述的最後一項定義了真正的Java模塊系統,它將會在JDK中以一個新JEP的形式來實現。sql

在2015年7月,JDK劃分爲哪些模塊已經大體肯定(參見JEP 200),JDK的源碼也進行了重構來適應這種變化(參見JEP 201),運行時鏡像(run-time image)也爲模塊化作好了準備(參見JEP 220)。全部的這些均可以在當前JDK 9的預覽版中看到。編程

針對JSR 376所開發的代碼很快將會部署到JDK倉庫中,可是使人遺憾的是,如今模塊化系統自己尚沒法體驗。(目前,Java 9的預覽版本已經包含了模塊化功能。——譯者注)安全

驅動力

在Jigsaw項目的歷史中,它的驅動力也發生過一些變化。最初,它只是想模塊化JDK。可是當人們意識到若是可以在庫和應用程序的代碼中也使用該工具的話,將會帶來很是大的收益,因而它的範圍獲得了擴展。#p#分頁標題#e#服務器

不斷增加且不可分割的Java運行時

Java運行時的大小在不斷地增加。可是在Java 8以前,咱們並無辦法安裝JRE的子集。全部的Java安裝包中都會包含各類庫的分發版本,如XML、SQL以及Swing的API,無論咱們是否須要它們,都要將其包含進來。架構

對於中等規模(如桌面PC和筆記本電腦)以上的計算設備來講,這不算是什麼嚴重的問題,可是對於小型的設備來講,這就很嚴重了,好比在路由器、TV盒子和汽車上,還有其餘使用Java的小地方。隨着當前容器化的趨勢,在服務器領域也有相關的要求,由於減小鏡像的大小就意味着下降成本。併發

Java 8引入了compact profile的功能,它們定義了三個Java SE的子集。在必定程度上緩解了這個問題,可是它們只有在嚴格限制的場景下才能發揮做用,profile過於死板,沒法涵蓋如今和將來全部使用JRE部分功能的需求。ide

JAR/Classpath地獄

JAR地獄和Classpath地獄是一種詼諧的說法,指的是Java類加載機制的缺陷所引起的問題。尤爲是在大型的應用中,它們可能會以各類方式產生使人痛苦的問題。有一些問題是由於其餘的問題而引起的,而有一些則是獨立的。

沒法表述依賴

JAR文件沒法以一種JVM可以理解的方式來表述它依賴於哪些其餘的JAR。所以,就須要用戶手動識別並知足這些依賴,這要求用戶閱讀文檔、找到正確的項目、下載JAR文件並將其添加到項目中。

並且,有一些依賴是可選的,只有用戶在使用特定功能的特性時,某個JAR纔會依賴另一個JAR。這會使得這個過程更加複雜。#p#分頁標題#e#

Java運行時在實際使用某項依賴以前,並不能探測到這個依賴是沒法知足的。若是出現這種狀況,將會出現NoClassDefFoundError異常,進而致使正在運行的應用崩潰。

像Maven這樣的構建工具可以幫助解決這個問題。

傳遞性依賴

一個應用程序要運行起來可能只需依賴幾個庫就足夠了,可是這些庫又會須要一些其餘的庫。問題組合起來會變得更加複雜,在所消耗的體力以及出錯的可能性上,它會呈指數級地增加。

一樣,構建工具可以在這個問題上提供一些幫助。

遮蔽

有時候,在classpath的不一樣JAR包中可能會包含全限定名徹底相同的類,好比咱們使用同一個庫的兩個不一樣版本。由於類會從classpath中的第一個JAR包中加載,因此這個版本的變種將會「遮蔽」全部其餘的版本,使它們變得不可用。

若是這些不一樣的變種在語義上有所差異,那將會致使各類級別的問題,從難以發現的不正常行爲到很是嚴重的錯誤都是有可能的。更糟糕的是,問題的表現形式是不肯定的。這取決於JAR文件在classpath中的順序。在不一樣的環境下,可能也會有所區別,例如開發人員的IDE與代碼最終運行的生產機器之間就可能有所差異。

版本衝突

若是項目中有兩個所需的庫依賴不一樣版本的第三個庫,那麼將會產生這個問題。#p#分頁標題#e#

若是這個庫的兩個版本都添加到classpath中的話,那麼最終的行爲是不可預知的。首先,由於前面所述的遮蔽問題,兩個版本的類中,只會有一個可以加載進來。更糟糕的是,若是某個類位於一個JAR包中,可是它所訪問的其餘類卻不在這個包中,這個類也可以加載。所致使的結果就是,對這個庫的代碼調用將會混合在兩個版本之中。

在最好的狀況下,若是試圖訪問所加載的類中不存在的代碼,將會致使明顯的NoClassDefFoundError錯誤。可是在最壞的狀況下,版本之間的差異僅僅是在語義上,實際的行爲會有細微的差異,這會引入很難發現的bug。

識別這種狀況所致使的難以預料的行爲是很困難的,也沒法直接解決。

複雜的類加載機制

默認狀況下,全部的類由同一個ClassLoader負責加載,在有些場景下,可能有必要引入額外的加載器,例如容許用戶加載新的類,對應用程序進行擴展。

這很快就會致使複雜的類加載機制,從而產生難以預期和難以理解的行爲。

在包之間,只有很弱的封裝機制

若是類位於同一個包中,那Java的可見性修飾符提供了一種很棒的方式來實現這些類之間的封裝。可是,要跨越包之間邊界的話,那隻能使用一種可見性:public。

由於類加載器會將全部加載進來的包放在一塊兒,public的類對其餘全部的類都是可見的,所以,若是咱們想建立一項功能,這項功能對某個JAR是可用的,而對於這個JAR以外是不可用的,這是沒有辦法實現的。#p#分頁標題#e#

手動的安全性

包之間弱封裝性所帶來的一個直接結果就是,安全相關的功能將會暴露在同一個環境中的全部代碼面前。這意味着,惡意代碼有可能繞過安全限制,訪問關鍵的功能。

從Java 1.1開始,有一種hack的方式,可以防止這種情況:每當進入安全相關的代碼路徑時,將會調用SecurityManager,並判斷是否是容許訪問。更精確地講,它應該在每一個這樣的路徑上都進行調用。過去,在有些地方遺漏了對它們的調用,從而出現了一些漏洞,這給Java帶來了困擾。

啓動性能

最後,Java運行時加載並JIT編譯所有所需的類須要較長的時間。其中一個緣由在於類加載機制會對classpath下的全部JAR執行線性的掃描。相似的,在識別某個註解的使用狀況時,須要探查classpath下全部的類。

目標

Jigsaw項目的目標就是解決上面所述的問題,它會引入一個語言級別的機制,用來模塊化大型的系統。這種機制將會用在JDK自己中,開發人員也能夠將其用於本身的項目之中。

須要注意的是,對於JDK和咱們開發人員來講,並非全部的目標都具備相同的重要性。有一些與JDK具備更強的相關性,而且大多數都對平常的編程不會帶來巨大的影響(這與最近的語言修改造成了對比,如lambda表達式和默認方法)。不過,它們依然會改變大型項目的開發和部署。

可擴展性的平臺

JDK在模塊化以後,用戶就能挑出他們須要的功能,並建立本身的JRE,在這個JRE中只包含他們須要的模塊。這有助於在小型設備和容器領域中,保持Java做爲關鍵參與者的地位。#p#分頁標題#e#

在這個提議的規範中,容許將Java SE平臺及其實現分解爲一組組件,開發人員能夠把這些組件組裝起來,造成自定義的配置,裏面只包含應用實際須要的功能。—— JSR 376

可靠的配置

經過這個規範,某個模塊可以聲明對其餘模塊的依賴。運行時環境可以在編譯期(compile-time)、構建期(build-time)以及啓動期(launch-time)分析這些依賴,若是缺乏依賴或依賴衝突的話,很快就會發生失敗。

強封裝

Jigsaw項目的一個主要目標就是讓模塊只導出特定的包,其餘的包是模塊私有的。

模塊中的私有類就像是類中的私有域。換句話說,模塊的邊界不只肯定了類和接口的可見性,還定義了它的可訪問性。——Mark Reinhold所撰寫的文章「Project Jigsaw:將宏偉藍圖轉換爲可聚焦的點」

 

提高安全性和可維護性

在模塊中,內部API的強封裝會極大地提高安全性,由於核心代���對於沒有必要使用它們的其他代碼來說是隱藏起來的。維護也會變得更加容易,這是由於咱們可以更容易地將模塊的公開API變得更小。

隨意使用Java SE平臺實現的內部API不只有安全風險,並且也會帶來維護的負擔。該提議規範可以提供強封裝性,這樣實現Java SE平臺的組件就能阻止對其內部API的訪問。 ——JSR 376#p#分頁標題#e#

提高性能

由於可以更加清晰地界定所使用代碼的邊界,現有的優化技術可以更加高效地運用。

不少預先(ahead-of-time)優化和全程序(whole-program)優化的技術會更加高效,由於可以得知某個類只會引用幾個特定組件中的類,它並不能引用運行時所加載的任意類。 —— JSR 376

核心概念

由於模塊化是目標,因此Jigsaw項目引入了模塊(module)的概念,描述以下:

命名、自描述的程序組件,會包含代碼和數據。模塊必須可以包含Java類和接口,組織爲包的形式,同時也能以動態加載庫的形式(dynamically-loadable library)包含原生代碼。模塊的數據必須可以包含靜態資源文件和用戶可編輯的配置文件。 —— Java平臺模塊系統:需求(草案2)

爲了可以基於必定的上下文環境來了解模塊,咱們能夠想一下知名的庫,如Google Guava或Apache Commons中的庫(好比Collections或IO),將其做爲模塊。根據做者但願劃分的粒度,每一個庫均可能劃分爲多個模塊。

對於應用來講也是如此。它能夠做爲一個單體(monolithic)的模塊,也能夠進行拆分。在肯定如何將其劃分爲模塊時,項目的規模和內聚性將是重要的因素。

按照規劃,在組織代碼時,模塊將會成爲開發人員工具箱中的常規工具。

#p#分頁標題#e#

開發人員目前已經可以考慮到一些標準的程序組件,如語言層面的類和接口。模塊將會是另一種程序組件,像類和接口同樣,它們將會在程序開發的各個階段發揮做用。 ——Mark Reinhold的文章「Project Jigsaw:將宏偉藍圖轉換爲可聚焦的點」

模塊又能夠進一步組合爲開發階段的各類配置,這些階段也就是編譯期、構建期、安裝期以及運行期。對於咱們這樣的Java用戶來講,能夠這樣作(在這種狀況下,一般會將其稱之爲開發者模塊),同時這種方式還能夠用來剖析Java運行時自己(此時,它們一般稱之爲平臺模塊)。

實際上,這就是JDK目前進行模塊化的規劃。

(點擊放大圖像)

特性

那麼,模塊是如何運行的呢?查閱一下Jigsaw項目的需求以及JSR 376將會幫助咱們對其有所瞭解。

依賴管理

爲了解決「JAR/Classpath地獄」的問題,Jigsaw項目的一個關鍵特性就是依賴管理。讓咱們看一下這些相關的組件。

聲明與解析

模塊將會聲明它須要哪些其餘的模塊才能編譯和運行。模塊系統會使用該信息傳遞性地識別全部須要的模塊,從而保證初始的那個模塊可以編譯和運行。#p#分頁標題#e#

咱們還能夠不依賴具體的模塊,而是依賴一組接口。模塊系統將會試圖據此識別模塊,這些模塊實現了所依賴的接口,可以知足依賴,系統會將其綁定到對應的接口中。

版本化

模塊將會進行版本化。它們可以標記本身的版本(在很大程度上能夠是任意格式,只要可以徹底表示順序就行),版本還能用於限制依賴。在任意階段都能覆蓋這兩部分信息。模塊系統會在各個階段都強制要求配置可以知足全部的限制。

Jigsaw項目不必定會支持在一個配置中存在某個模塊的多個版本。可是,稍等,那該如何解決JAR地獄的問題呢?好問題!

版本選擇——針對同一個模塊,在一組不一樣版本中挑選最合適的版本——並無做爲規範所要完成的任務。因此,在我撰寫的上文中,模塊系統會識別所需的模塊進行編譯,在運行時則可能會使用另一個模塊,這都基於一個假設,那就是環境中只存在模塊的一個版本。若是存在多個版本的話,那麼上游的步驟(如開發人員或者他所使用的構建工具)必需要作出選擇,系統只會校驗它能知足全部的約束。

封裝

模塊系統會在各個階段強制要求強封裝。這是圍繞着一個導出機制實現的,在這種狀況下,只有模塊導出的包才能訪問。封裝與SecurityManager所執行的安全檢查是相獨立的。

這個提議的具體語法尚沒有定義,可是JEP 200提供了一些關鍵語義的XML實例。做爲樣例,以下的代碼聲明瞭java.sql模塊。

#p#分頁標題#e#<module>

  <!-- 模塊的名字 -->
  <name>java.sql</name>

  <!-- 每一個模塊都會依賴java.base -->
  <depend>java.base</depend>

  <!-- 這個模塊依賴於java.logging和java.xml
       模塊,並從新導出這些模塊所導出的API包 -->
  <depend re-exports="true">java.logging</depend>
  <depend re-exports="true">java.xml</depend>

  <!-- 這個模塊導出java.sql、javax.sql以及
       javax.transaction.xa包給其餘任意的模塊 -->
  <export><name>java.sql</name></export>
  <export><name>javax.sql</name></export>
  <export><name>javax.transaction.xa</name></export>

</module>

從這個代碼片斷咱們能夠看出,java.sql依賴於java.basejava.logging以及java.xml。在稍後介紹不一樣的導出機制時,咱們就能理解上文中其餘的聲明瞭。

導出

模塊會聲明特定的包進行導出,只有包含在這些包中的類型才能導出。這意味着其餘模塊只能看到和使用這些類型。更嚴格是,其餘模塊必需要顯式聲明依賴包含這些類型的模塊,這些類型才能導出到對應的模塊中。

很是有意思的是,不一樣的模塊可以包含相同名稱的包,這些模塊甚至還可以將其導出。

在上面的樣例中,java.sql導出了java.sqljavax.sql以及javax.transaction.xa這些包。

從新導出

咱們還可以在某個模塊中從新導出它所依賴的模塊中的API(或者是其中的一部分)。這將會對重構提供支持,咱們可以在不破壞依賴的狀況下拆分或合併模塊,由於最初的依賴能夠繼續存在。重構後的模塊能夠導出與以前相同的包,即使它們可能不會包含全部的代碼。在極端的狀況下,有一種所謂的#p#分頁標題#e#聚合器模塊(aggregator module),它能夠根本不包含任何代碼,只是做爲一組模塊的抽象。實際上,Java 8中所提供的compact profile就是這樣作的。

從上面的例子中,咱們能夠看到java.sql從新導出了它依賴的API,即java.loggingjava.xml

限制導出

爲了幫助開發者(尤爲是模塊化JDK的人員)讓他們所導出API的有較小的接觸面,有一種可選的限制導出(qualified export)機制,它容許某個模塊將一些包聲明爲只針對一組特定的模塊進行導出。因此使用「標準」機制時,導出功能的模塊並不知道(也不關心)誰會訪問這些包,可是經過限制導出機制,可以讓一個模塊限定可能產生的依賴。

配置、階段以及保真性(Fidelity)

如前所述,JEP 200的目標之一就是模塊可以在開發的各個階段組合爲各類配置。對於平臺模塊能夠如此,這樣就可以建立與完整JRE或JDK相似的鏡像,Java 8所引入的compact profile以及包含特定模塊集合(及其級聯依賴)的任意自定義配置都使用了這種機制。相似的,開發人員也可使用這種機制來組合他們應用程序的不一樣變種。

在編譯期(compile-time),要編譯的代碼只能看到所配置的模塊集合中導出的包。在構建期(build-time),藉助一個新的工具(可能會被稱爲JLink),咱們可以建立只包含特定模塊及其依賴的二進制運行時鏡像。在安裝期(launch-time),鏡像可以看起來就像是隻包含了它所具備的模塊的一個子集。

咱們還可以替換實現了受權標準(endorsed standard)和獨立技術(standalone technology)的模塊,在任意的階段都能將其替換爲較新的版本。這將會替代已廢棄的受權標準重載機制(endorsed standards override mechanism)以及擴展機制(參見下文。)#p#分頁標題#e#

模塊系統的各個方面(如依賴管理、封裝等等),在全部階段的運行方式是徹底相同的,除非由於特定的緣由,在某些階段沒法實現。

模塊相關的全部信息(如版本、依賴以及包導出)都會在代碼文件中進行描述,這樣會獨立於IDE和構建工具。

性能

全程序優化的技術

在模塊系統中,藉助強封裝技術,可以很容易自動計算出一段特定的代碼都用在了哪些地方。這會使得程序分析和優化技術更加可行:

快速查找JDK和應用程序的類;及早進行字節碼的檢驗;積極級聯(aggressive inlining)像lambda表達式這樣的內容以及其餘的編譯器優化;構建特定於JVM的內存鏡像,它加載時可以比類文件更加高效;預先將方法體編譯爲原生代碼;移除沒有用到的域、方法和類。——Jigsaw項目: 目標 & 需求(草案3)

有一些被稱爲全程序優化(whole-program optimization)的技術,在Java 9中至少會實現兩種這樣的技術。還有包含一個工具,使用這個工具可以分析給定的一組模塊,並使用上述的優化技術,建立更加高性能的二進制鏡像。

註解

目前,要自動發現帶有註解的類(如Spring註解標註的配置類),須要掃描特定包下的全部類。這一般會在程序啓動的時候完成,這在至關程度上會減慢啓動的過程。

模塊將會提供一個API,容許調用者識別全部帶有給定註解的類。一種預期的方式是爲這樣的類建立索引,這個索引會在模塊編譯的時候建立。#p#分頁標題#e#

與已有的概念和工具集成

診斷工具(如棧跟蹤信息)將會進行更新,其中會包含模塊的信息。並且,它們還會集成到反射API中,這樣就能按照操做類的方式來使用它們,還會包含版本信息,這一信息能夠進行反射,也能夠在運行時重載。

模塊的設計可以���咱們在使用構建工具時「儘量地減小麻煩(with a minimum of fuss)」。編譯以後的模塊可以用在classpath中,也能做爲一個模塊來使用,這樣的話,庫的開發人員就沒有必要爲classpath應用和基於模塊的應用分別建立多個構件了。

與其餘模塊系統的相互操做也進行了規劃,這其中最著名的也就是OSGi。

儘管模塊可以對其餘的模塊隱藏包,可是咱們依然可以對模塊包含的類和接口執行白盒測試。

特定OS的包

模塊系統在設計時,始終考慮到了包管理器文件格式,「如RPM、Debian以及Solaris IPS」。開發人員不只可以使用已有的工具將一組模塊集合建立爲特定OS的包,這些模塊還能調用按照相同機制安裝的其餘模塊。

開發人員還可以將組成應用的一組模塊打包爲特定OS的包,「終端用戶可以按照目標系統的通用作法,安裝和調用所打成的包」。基於上述的介紹,咱們能夠得知只有目標系統中不存在的模塊才必需要打包進來。

動態配置

正在運行中的應用可以建立、運行併發布獨立的模塊配置。在這些配置中,能夠包含開發者和平臺模塊。對於容器類架構,這會很是有用,如IDE、應用服務器或其餘Java EE平臺。#p#分頁標題#e#

不兼容性

按照Java的慣例,這些變動在實現時,會強烈關注到向後的兼容性,全部標準和非廢棄的API及機制都可以繼續使用。可是項目可能會依賴其餘缺少文檔的構造,這樣的話,在往Java 9遷移的時候,就須要一些額外的工做了。

內部API不可用了

藉助於強封裝,每一個模塊可以明確聲明哪些類型會做爲其API的一部分。JDK將會使用這個特性來封裝全部的內部API,所以它們會變得不可用了。

在Java 9所帶來的不兼容性中,這多是涵蓋範圍最大的一部分。可是這也是最明顯的,由於它會致使編譯錯誤。

那麼,什麼是內部API呢?毫無疑問,位於sun.*包中的全部內容。若是位於com.sun.*包中,或者使用了@jdk.Exported註解,在Oracle JDK中它依然是可用的,若是沒有註解的話,那麼它就是不可用的了。

能產生特殊問題的一個樣例就是sun.misc.Unsafe類。它用在了不少項目中,用來實現關鍵任務或性能要求較高的代碼,它未來可能不可用引起了不少的相關討論。不過,在一次相關的交流中曾經提出,經過一個廢棄的命令行標記,它依然是可用的。考慮到沒法將其全部的功能都放到公開API中,這多是一種必要的權衡。

另一個樣例是com.sun.javafx.*包中的全部內容。這些類對於構建JavaFX控件是相當重要的,而且它們還有必定數量的bug要修改。這些類中的大多數功能都會做爲發佈的目標。

合併JDK和JRE#p#分頁標題#e#

在具備可擴展的Java運行時以後,它容許咱們很靈活地建立運行時鏡像,JDK和JRE就喪失了其獨有的特性,它們只是模塊組合中的兩種形式而已。

這意味着,這兩個構件將會具備相同的結構,包括目錄結構也相同,任何依賴它(如在原來的JDK目錄中會有名爲jre的子目錄)的代碼就不能正常運行了。

內部JAR不可用了

lib/rt.jarlib/tools.jar這樣的內部JAR將不可用了。它們的內容將會存儲到特定實現的文件中,這些文件的格式還未明確說明,有可能會發生變化。

任何假設這些文件存在的代碼將沒法正確運行。這可能對IDE或其餘嚴重依賴這些文件的工具帶來一些切換的麻煩。

針對運行時鏡像內容的新URL模式

在運行時,有些API會返回針對類和資源文件的URL(如ClassLoader.getSystemResource)。在Java 9以前,它們都是jar URL,格式以下:

jar:file:<path-to-jar>!<path-to-file-in-jar>

Jigsaw項目將會使用模塊做爲代碼文件的容器,單個JAR將不可用了。這須要一個新的格式,因此這些API將會返回jrt URL:

jrt:/<module-name>/<path-to-file-in-module>

若是使用這些API所返回的實例來訪問文件的代碼(如URL.getContent),那麼運行方式會和如今同樣。可是,若是依賴於jar URL的#p#分頁標題#e#結構(好比手動構建它們或對其進行解析),那麼就會出錯了。

移除受權標準重載機制

有一些Java API被稱爲「獨立技術(Standalone Technology)」,它們的建立是在Java Community Process(如JAXB)以外的。對它們來講,有可能會升級其依賴或使用替代實現。受權標準重載機制容許在JDK中安裝這些標準的替代版本。

這種機制在Java 8中已經廢棄了,在Java 9中將會移除,會由上文所述的可升級模塊來替代。

移除擴展機制

藉助擴展機制,自定義API可以被JDK中運行的全部應用程序使用,而沒必要在classpath中對其進行命名。

這種機制在Java 8中已經廢棄了,在Java 9中將會移除。有些自己有用的特性將會保留。

接下來要作什麼?

咱們已經簡要了解了Jigsaw項目的歷史,看到是什麼在驅動它的發展並討論了它的目標,如何經過一些特性來實現這些目標。除了等待Java 9之外,咱們還能作些什麼呢?

準備

咱們應該爲本身的項目作一些準備工做,檢查它們是否依賴Java 9中將要移除的內容。

至少,在檢查內部API依賴方面再也不須要手動搜索了。從Java 8開始,JDK包含了Java依賴分析工具(Java Dependency Analysis Tool),名爲#p#分頁標題#e#JDeps (介紹了一些內部的包,官方有針對Windows以及Unix的文檔),它可以列出某個項目依賴的全部的包。若是在運行時使用-jdkinternals參數的話,那麼它將會列出該項目所使用的幾乎全部的內部API。

之因此說「幾乎全部」是由於它還沒法識別Java 9中不可用的全部的包。這至少會影響到JavaFX所屬的包,能夠查看JDK-8077349。(經過使用這個搜索,除了缺失的功能之外,我沒能發現其餘的缺陷。)

至少存在三個用於Maven的JDeps插件:分別由Apache、Philippe Marschall以及我本人所提供。就目前來說,最後一個是惟一當jdeps -jdkinternals報告中依賴內部API時,致使構建失敗的插件。(如今,Apache的插件在出現內部API依賴時,也會提示構建失敗,參見InfoQ的這篇新聞。——譯者注)

討論

Jigsaw項目最新的消息來源於Jigsaw-Dev郵件列表。我也會在博客中繼續討論這個話題。

若是你擔憂某個特定的API在Java 9中不可用的話,那麼你能夠查看相關OpenJDK項目的郵件列表,由於他們會負責開發公開的版本。

採用

Java 9的早期試用構建版本已經可用了。不過,JSR 376依然處於開發階段,在這些構建版本中尚沒法使用模塊系統,還會有不少的變化。(在目前的試用版中,已經包含了Jigsaw,不過最新的消息是Java 9又要延期六個月發佈了。——譯者注)實際上,除了強封裝之外,其餘的功能都已經就緒了。

將收集到的消息發送給Jigsaw-Dev郵件列表可以反饋給項目。最後,引用JEP 220(臨近)結尾的一段話:#p#分頁標題#e#

咱們不可能抽象地肯定這些變動的所有影響,因此必需要依賴普遍的內部測試,尤爲重要的還有外部測試。[……]若是有些變動會給開發人員、部署人員或終端用戶帶來難以承受的負擔,那麼咱們將會研究減小其影響的方式。

另外,還有一個全球的Java用戶羣組AdoptOpenJDK,它可以很好地將早期試用者聯繫起來。

關於做者

Nicolai Parlog是一名軟件開發人員,對Java充滿熱情。他不斷地閱讀、思考以及撰寫與Java相關的內容,他靠編碼爲生,也以此爲樂。他是多個開源項目的長期貢獻者,並在CodeFX上用博客記錄軟件開發相關的內容。你能夠在Twitter上關注Nicolai。

相關文章
相關標籤/搜索