Java

Java 9的Module System簡介

Module System

由於許多公司和主流平台都還是使用Java 8為預設執行環境,導致Java雖然每六個月就會有一版新的release,但多數開發人員都不會特別升版,因此自然新功能注意的人也就少。這篇文章先開始由Java 9 module系統的簡介開始說起,後續會以此為開頭慢慢介紹各版本的Java大概多了哪些功能。

Why Java Platform Module System?

在Java 8以前,library雖然可以用jar files的形式管理,但實際上在執行的時候,每個jar檔案分離管理其實也就只是在檔案層級看起來是分離的,實際運作其實所有的class都是在classpath上摻在一起做撒尿牛丸(?),class可隨意互相存取,毫無限制。這樣的機制在security、設計和長期維護的觀點來看,一直都有很大的”改善空間”。

Module Descriptors

為了作到backward compatible,Java 9引入的module system多導入了一個module-info.java檔案,內容定義該module需要export的packages有哪些,也定義了該module相依於哪些modules。且在設計上為了避免新引入的keyword衝突到使用者舊版的應用程式,也刻意將如module, exports, requires這類新的keywords只限縮在module-info.java檔案。

Java 8的應用程式轉到Java 9

轉移Java 8的applications到Java 9過程中,多數的應用程式都能無痛轉移。除了以下兩點需要特別處理:

1. 使用到JDK內被encapsulated的部份

若原source code有使用到JDK內被encapsulated的部份,會發現拿到Java 9上compile下去就會看到類似以下的錯誤訊息:

Error:(?, ?) java: package  is not visible
  (package XXX is declared in module YYY, which does not export it to the unnamed module)

首先需要說明一下這unnamed module是什麼。Java 8的code轉到Java 9 compile後,在沒有module descriptor的情況下,原本的classes都會自動被歸屬到一個稱為”unnamed”的module,且這module會自動加上JDK modules的相依性以確保功能運作正常。

了解了unnamed module是什麼,上述的錯誤訊息就好懂的多。簡單的說就是在unnamed module那些原本的classes,有用到了一些module是沒有export給unnamed module的。不過由於Java community在設計module system的時候就有考慮到這轉換過渡期的痛點,所有有提供Java 9的java和javac指令–add-exports或–add-opens參數暫時先開放這些已被封裝起的packages。不過長遠來說仍要找時間修改掉這類dependencies,以確保後續Java版本還能正常運作。

除了上述方式外,另外一個繞過此限制的方式,則是把source code仍用Java 8編譯,然後跑在Java 9。由於各類情境有些複雜,以下簡單做成一個表格說明:

Java 8的code,編譯用JDK8Java 8的code,編譯用JDK9
執行用Java 8舊的組合,運作正常若在編譯時沒有加上任何參數,Java是無法用新版本編譯,然後跑在舊版本。不過在JDK9的javac可以使用參數-release來產生舊版JDK支援的output。
執行用Java 9可正常執行。但若加上–illegal-access=deny參數則會強制開啟module規範,可能導致舊code無法執行。編譯和執行時都會強制module的規範。若要暫時打破規範,可使用–add-exports或–add-opens暫時先繞過此限制。

除了在compile或runtime的時候才發現module的錯誤外,Java另外還提供了一個jdeps的指令讓使用者分析程式的dependencies。不同於compile或runtime單純的錯誤訊息,jdeps在分析後還會提供誤用encapsulated classes的替代方案(suggested replacement)。

2. 使用到非Java default modules

Java 9把數個modules獨立分開到一個package稱為java.se.ee,並將其標注為Deprecated。這些modules若在原本的code有使用到的話,在compile或執行的時候也會出現錯誤。若要讓application仍能順利執行,可加上參數–add-modules在javac或java指令後即可。這類問題也能透過jdeps指令找到(結果上會顯示該package為not found)。

Add a Comment

Your email address will not be published. Required fields are marked *