如何針對Java9之前版本構建一個既模組化又相容Java版本的庫呢
如果您是庫包或框架的作者,你可能希望看到你的庫包在大量應用程式中使用。提升庫包使用量的一種方法是使其與舊版Java相容。同時,你可以考慮對庫進行模組化,以使其對充分利用Java平臺模組系統(JPMS)的應用程式具有吸引力。
但是,JPMS僅由Java 9和更新版本實現。那麼,如何在9之前構建一個既模組化又相容Java版本的庫呢?
模組化jar只是一個普通的jar,它包含一個module-info.class代表模組描述符的檔案。通常通過編譯相應的module-info.java檔案來生成該模組描述符。
在Java 8及更早版本上執行時,將忽略模組描述符,因為module-info不是它的合法的Java識別符號。這意味著可以通過為目標庫的版本建立普通jar並在其中插入模組描述符來生成與Java 9之前版本相容的模組化jar。
執行這樣的辦法的標準方法意味著呼叫java編譯器兩次:
- 編譯所有源,除了module-info.java使用適當的javac標記引數才能提供Java 9之前版本的相容性。
- 使用Java編譯器9+編譯module-info.java。
Mavenofollow,noindex" target="_blank">描述 了一種符合上述策略的構建方法。
另一種解決方案是ModiTect ,一個用於Java 9模組系統的Maven外掛。ModiTect提供的目標之一是add-module-info,它允許您將模組描述符新增到當前Maven專案生成的JAR中:
<plugin> <groupId>org.moditect</groupId> <artifactId>moditect-maven-plugin</artifactId> <version>1.0.0.Beta1</version> <executions> <execution> <id>add-module-infos</id> <phase><b>package</b></phase> <goals> <goal>add-module-info</goal> </goals> <configuration> <jvmVersion>11</jvmVersion> <module> <moduleInfoFile> ${basedir}/src/main/java/module-info.java </moduleInfoFile> </module> </configuration> </execution> </executions> </plugin>
ModiTect使用一種聰明的技術來建立模組描述符,而無需Java編譯器。它使用JavaParser 分析module-info.java檔案,並使用 ASM 位元組碼操作框架生成相應的模組描述符。這樣,即使您使用Java 9之前的編譯器,它也允許您建立模組化jar。
從ModiTect的方法中汲取靈感,我實現了一個Gradle外掛, 用於建立面向Java 8或更早版本的模組化jar。
使用這個外掛非常簡單:build.gradle只需要新增外掛並指定庫所針對的Java版本:
plugins { id 'java' id 'org.beryx.jar' version '1.0.0' } sourceCompatibility = 1.8 targetCompatibility = 1.8
將module-info.java檔案放在src/main/java專案目錄中後,您可以使用以下命令構建模組化jar:
./gradlew jar
不需要Java 9+編譯器來構建模組化jar,因為該外掛使用與ModiTect相同的技術。但是,請記住,此技術無法檢查模組描述符的有效性。指向不存在的包,模組,服務或服務實現將不會被發現。
因此,強烈建議通過使用Java 9+編譯器和sourceCompatibility與targetCompatibility設定進行額外構建專案來驗證模組描述符,好訊息是您不需要更改構建指令碼來執行此操作。該外掛允許您通過設定專案屬性來覆蓋sourceCompatibility和targetCompatibility值javaCompatibility:
./gradlew -PjavaCompatibility=9 jar
請注意,此專案屬性會使用相同的值覆蓋兩者sourceCompatibility並targetCompatibility
如果外掛檢測到至少有一個sourceCompatibility並且targetCompatibility有效值> = 9,它會自動應用Chainsaw 外掛,這會增加對JPMS的支援。這就是為什麼在Java 9+相容模式下執行時,構建指令碼不需要進行任何更改。
...