Jigsaw項目另起爐灶
Mark Reinhold 在 jigsaw-dev 郵件列表上發言表示,Jigsaw 項目將在一個新的 Hg 倉庫上另起爐灶,再次嘗試解決讓 JDK 實現模塊化的難題。新倉庫位于 http://hg.openjdk.java.net/jigsaw/jake。
Jigsaw 項目遷延日久,向前可追溯到最初的 JSR 277和和稍晚的 JSR 294,原本設定的目標是將 Java 的核心運行時庫解耦,拆分為若干模塊。如果成功實現的話,純服務器端的 JVM 運行的時候將終于可以不必帶著用不上的 AWT 支持。
對 JDK 進行模塊化拆分,這件事情很不簡單。例如按照現在的設計,java.beans
、java.applet
和java.awt
包之間依次存在依賴關系。即使我們真的能夠在那么多年后推翻原來的設計決策,取消它們的依賴關系,也很難不顧此失彼。
Java 其實老早就有一個模塊系統,起初叫做 JSR 8,也就是現在的 OSGi 和 JSR 291。這個系統被所有的主流 Java EE 應用所采用,在其他領域的系統和應用中也運用得非常廣泛(如 JIRA、Eclipse),還進入了某些特定的垂直市場(如嵌入式系統、家庭自動化)。在這樣的背景下,Jigsaw 項目學習java.util.Date
、Java IO NIO NIO2 NIO2.2、java.logging
包等前輩的榜樣,丟開最佳實踐,存心湊合一套給 JDK 自己用的系統。(好在 Java 8 總算收拾了java.util.Date
這個怪胎,納入了 Joda-Time,也就是新的 java.time 包來作為對java.util.Date
的修正的修正。)
每一回 JSR 277/Jigsaw 推倒重來,目標都要打一點折扣。最早的時候,它是一個適用于任何應用的通用模塊系統,且具備解析鏈和倉庫存儲機制。(照 Java 的慣例,系統會設計成可插拔的,我們會見到 ModuleFactory 和 ModuleResolverFactory。)差不多 5 年前的2008 年 12 月,JSR 277 好像走進了死胡同。于是項目的目標經過重新評估,一種可以聚合多個包,但只對外暴露單一個包或單一組 API 的“超級包”概念被提了出來,從而誕生了 JSR 294。
到了 JSR 294 也徘徊不前的時候,又誕生了 Jigsaw 項目,目標相應地變更為實現一個主要為 JVM 本身服務的模塊系統(但同時為用于其他系統留有余地)。Jigsaw 放棄了一些理所當然的特性,如模塊解析鏈,只定位在給 Java 提供基本的模塊定義能力。Jigsaw 提出的方案犯了一個關鍵錯誤,它讓模塊通過執行代碼的方式,而非聲明式的方式來表達依賴關系,其結果造成我們不可能通過靜態分析來確定一個模塊系統成立與否。(不能靜態檢查約束條件是否滿足的模塊系統,有一個現成的例子,也就是我們熟悉的“classpath”,現在通常可以在小規模的應用和一些 IDE 中見到。)
大約 1 年前,Mark Reinhold 撰文“Project Jigsaw: Late for the Train”,宣布 Jigsaw 項目將錯過 Java 8 的發布日程。這件事情的反響毀譽參半,OSGi 的支持者和反對者們各自宣告勝利或失敗;Jigsaw 推遲到 Java 9 才定案,好歹讓該項目有機會修正一些錯誤決策。
這一次另起爐灶,Mark Reinhold 希望拿出一個不那么雄心勃勃的系統原型,一方面保留現有的由解析代理來提供各種 JAR 的方式,另一方面新增一種靜態描述元素間模塊依賴關系的手段。眼下新倉庫中的代碼僅僅是從 JDK8 拷貝過來的一個分支,但按照打算,這次會拋棄那些一直以來拖后腿的包袱,在上一輪嘗試中成為問題根源的一些設計決策,將得到重新審視。
我們的計劃之一,是避免像當前原型那樣引入專門的“模塊模式”(此模式與一些由來已久的習慣做法向左,會導致某些不普遍、但有深刻影響的兼容問題),也不負責解析依賴關系(因為這件事情 Maven、Ivy、Gradle 等構建工具已經做得夠好了),在這樣的前提下驗證可行的方案。我們的新原型會從舊的原型中借鑒合理的代碼,但最重要的還是借機重估原來的一些設計決策,并且做一次全面的清理。
尚待決斷的重要設計決策有:
- 版本號是遵守一種現成的版本號格式系統,如 Semantic Versioning,還是編到哪算哪
- 模塊系統是(像 Ivy、Maven 和 Gradle 那樣)聲明式地表述依賴關系,還是必須通過執行代碼來確定依賴關系(并因此阻礙靜態分析和事先核驗)
- 模塊系統是(像 OSGi 那樣)動態的,還是(像 Maven 那樣)靜態的;換言之,模塊可以隨增隨減,還是只進不出
- 賴關系的元數據是放在 JVM 能理解的 .class 文件里,還是用 JSON、YAML、Manifest.MF 之類的文本格式來保存
以 Oracle 對外來方案的排斥,選擇 OSGi 作為 Jigsaw 實現基礎的可能性很低。另一方面,OSGi 作為一種完全動態的方案,用作 JVM 的模塊化機制也顯得過火。最好的折中方案可能是一種近似于 OSGi,具有版本化的依賴項管理和 bundle 機制,但去除動態特征(及因此導致的多重 classloader)的系統。用 Java 來實現類似系統的可能性,已經在 pojosr 項目中得到證明,我們也許會見到一個皆大歡喜的結果。 英文原文:Jigsaw, Second Cut