2021年12月25日 星期六

5.1 在命令列(command line)使用模組指令選項-java

指令java除了可以執行Java SE類別裡的main()方法之外,還有與模組相關的選項,常見有以下3個:

java指令選項

作用

--describe-module

描述模組內容

--list-modules

列舉可用模組清單

--show-module-resolution

解析模組執行時的步驟

因為專案zoo.staffmods目錄內有打包好的全部的模組JAR檔案,因此執行指令時預設的路徑是專案zoo.staff的根目錄,以本書為例是C:\java11\code\zoo.staff

後續將逐一說明與示範。

使用選項--describe-module

假設我們拿到一個模組zoo.animal.feeding的JAR檔案,並且想了解它的模組結構。我們可以把該JAR檔案與以解壓縮並瀏覽module-info.java檔案如下。檔案內容顯示該模組exports一個套件並且不需要任何模組:

module zoo.animal.feeding {
    exports zoo.animal.feeding;
}
不過還有一種更簡單的方法,就是使用java指令的「--describe-module」選項來描述一個模組:
java -p mods
--describe-module zoo.animal.feeding
指令選項「--describe-module」可以使用「-d」簡化,所以執行指令「java -p mods -d zoo.animal.feeding」時可以得到相同的結果:

摘錄文字結果:

1

zoo.animal.feeding file:///C:/java11/code/zoo.animal.feeding/mods/zoo.animal.feeding.jar

2

exports zoo.animal.feeding

3

requires java.base mandated

說明:

1

輸出模組名稱與JAR實體檔案路徑。

2

exports套件zoo.animal.feeding,這部分與模組資訊檔內容相同。

3

這一行是模組系統自動加上的。

如同編寫類別程式碼時會自動imports基礎java.lang套件,模組系統也會自動註記所有模組都需要基本的java.base模組,關鍵字「mandated」就是如此意含,指出如java.base模組並沒有明確宣告在模組資訊檔中,但因為規格授權還是會自動出現。

類似的情境,針對模組zoo.animal.care,再比較模組資訊檔與java指令描述模組的差異。模組資訊檔如下:

module zoo.animal.care {
    exports zoo.animal.care.medical;
    requires transitive zoo.animal.feeding;
}

執行指令「java -p mods -d zoo.animal.care」將得到以下結果:

1

zoo.animal.care file:///C:/java11/code/zoo.animal.care/mods/zoo.animal.care.jar

2

exports zoo.animal.care.medical

3

requires java.base mandated

4

requires zoo.animal.feeding transitive

5

contains zoo.animal.care.details

指令結果比模組資訊檔多了行3與行5。行3在前例已經解釋,行5則是點出了模組內未以exports公開的套件。

模組中未使用exports公開的套件,將會使用contains宣告以表示供模組內部使用。

使用選項--list-modules

除了描述模組之外,還可以使用java指令列出可用的模組。未指定模組JAR檔案路徑時,將列出屬於JDK的模組:以下是指令
java --list-modules

的執行結果:

輸出的行數很多,這裡只節錄開頭幾行。內容是Java內建的所有模組及其版本號的列表,可以看出執行指令是Java11.0.12版。

若指令中包含zoo專案的所有模組JAR檔案:

java -p mods --list-modules

則執行結果就是前述的行內容加上4zoo專案的模組JAR檔:

使用選項--show-module-resolution

使用選項--show-module-resolution可以視為debug模組的一種手段。因為它會執行模組,並輸出過程,最後並輸出執行結果。
執行以下指令前先切換至專案zoo.animal.feeding的根目錄,如C:\java11\code\zoo.animal.feeding:
java --show-module-resolution 
-p src 
-m zoo.animal.feeding/zoo.animal.feeding.Task

以下節錄過程的一些輸出內容,最後一行是執行結果:

root zoo.animal.feeding file:///C:/java11/code/zoo.animal.feeding/src/

java.base binds jdk.localedata jrt:/jdk.localedata

java.base binds jdk.zipfs jrt:/jdk.zipfs

java.base binds jdk.charsets jrt:/jdk.charsets

java.base binds jdk.security.auth jrt:/jdk.security.auth

...

java.security.sasl requires java.logging jrt:/java.logging

java.naming requires java.security.sasl jrt:/java.security.sasl

jdk.security.jgss requires java.logging jrt:/java.logging

...

All are fed!

它首先列出根(root)模組,本例是zoo.animal.feeding;然後列出了java.base模組所包含的多行套件,也會列出具有相依關係的模組。最後它輸出指定類別zoo.animal.feeding.Task的執行結果。


沒有留言:

張貼留言