日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Java Platform Module系统中的可选依赖项

發(fā)布時間:2023/12/3 windows 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Platform Module系统中的可选依赖项 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Java平臺模塊系統(tǒng)(JPMS)對依賴項有很強的見解:默認情況下,需要(必須可訪問)它們,然后在編譯時和運行時都將它們存在。 但是,這不適用于可選的依賴項,因為代碼是針對運行時不一定存在的工件編寫的。 幸運的是,JPMS有一個require靜態(tài)子句,可以在這些確切的情況下使用。

我將向您展示幾個示例,在這些示例中,默認行為的嚴格性會導(dǎo)致問題,然后向可選依賴項介紹模塊系統(tǒng)的解決方案:需要靜態(tài)。 但是,對它們進行編碼并非易事,因此我們也會對此進行仔細研究。

總覽

一些示例建立在一個名為Service Monitor 的小型演示應(yīng)用程序 的optional-dependencies分支上。

不需要的依賴之謎

為了確定常規(guī)的require子句的嚴格性會導(dǎo)致問題的原因,我想從兩個示例開始。 盡管在某些方面相似,但是稍后在討論如何針對可能缺少的依賴項進行編碼時,差異變得很重要。

實用程序庫

讓我們從我們正在維護的虛構(gòu)庫uber.lib開始,該庫與少數(shù)其他庫集成。 它的API提供了基于它們的功能,因此可以公開其類型。 我們將通過com.google.guava的示例進行演示 ,在我們的假設(shè)場景中,該示例已經(jīng)變成了uber.lib想要針對其進行編碼的Java模塊。

作為uber.lib的維護者,我們假設(shè)沒有使用Guava的人永遠不會調(diào)用我們庫的Guava部分。 在某些情況下,這很有意義:如果沒有這樣的圖,為什么還要在uber.lib中調(diào)用為com.google.common.graph.Graph實例創(chuàng)建漂亮報告的方法?

對于uber.lib ,這意味著它無需com.google.guava即可完美運行:如果Guava將其放入模塊圖中 ,則客戶端可能會調(diào)用uber.lib API的該部分。 如果沒有,他們也不會,圖書館也會很好。 我們可以說uber.lib從不需要它自己的依賴。

具有常規(guī)依賴性,無法實現(xiàn)可選關(guān)系。

但是,使用常規(guī)的require子句無法實現(xiàn)這種可選關(guān)系。 根據(jù)可讀性和可訪問性規(guī)則, uber.lib必須要求com.google.guava對其類型進行編譯,但這會強制所有客戶端在啟動其應(yīng)用程序時始終在模塊路徑上使用Guava。

如果與圖書館屈指可數(shù)uber.lib集成,它將使客戶依賴于所有的人,即使他們可能永遠不會使用超過一個。
這不是我們的好舉動。

花式統(tǒng)計圖書館

第二個示例來自演示應(yīng)用程序 ,該應(yīng)用程序包含一個模塊monitor.statistics 。 假設(shè)有一些高級統(tǒng)計信息庫,其中包含monitor.statistics要使用的模塊stats.fancy ,但對于應(yīng)用程序的每次部署,該信息都不會出現(xiàn)在模塊路徑中。 (這樣做的原因無關(guān)緊要,但是讓我們一起使用一個許可證,該許可證可以防止將花哨的代碼“用于邪惡”,但是,作為我們的邪惡策劃者,我們有時只想這樣做。)

我們想在monitor.statistics中編寫代碼,該代碼使用fancy模塊中的類型,但是要使其正常工作,我們需要使用require子句來依賴它。 但是,如果執(zhí)行此操作,則在不存在stats.fancy的情況下,模塊系統(tǒng)將不會啟動應(yīng)用程序。

僵局。 再次。

帶有“需要靜態(tài)”的可選依賴項

當一個模塊需要針對另一個模塊的類型進行編譯,但又不想在運行時依賴它時,可以使用require靜態(tài)子句。 如果foo需要靜態(tài)bar,則模塊系統(tǒng)在編譯和運行時的行為會有所不同:

  • 在編譯時, bar必須存在,否則會出現(xiàn)錯誤。 在編譯過程中的酒吧是FOO可讀。
  • 在運行時,可能不存在bar ,這將不會導(dǎo)致錯誤或警告。 如果存在,則foo可以讀取。

我們可以立即將其付諸實施,并創(chuàng)建一個可選的依賴項,從monitor.statistics到stats.fancy :

module monitor.statistics {requires monitor.observer;requires static stats.fancy;exports monitor.statistics; }

如果在編譯過程中缺少stats.fancy,則在編譯模塊聲明時會出現(xiàn)錯誤:

monitor.statistics/src/main/java/module-info.java:3:error: module not found: stats.fancyrequires static stats.fancy;^ 1 error

但是,在啟動時 ,模塊系統(tǒng)不在乎stats.fancy是否存在。

同樣, uber.lib的模塊描述符將所有依賴項聲明為可選:

module uber.lib {requires static com.google.guava;requires static org.apache.commons.lang;requires static org.apache.commons.io;requires static io.javaslang;requires static com.aol.cyclops; }

現(xiàn)在我們知道了如何聲明可選的依賴關(guān)系,還有兩個問題需要回答:

  • 在什么情況下會出現(xiàn)?
  • 我們?nèi)绾吾槍蛇x依賴項進行編碼?

接下來,我們將回答兩個問題。

喜歡我的帖子? 然后拿我的書! Java 9模塊系統(tǒng)

  • 模塊系統(tǒng)的深入介紹:
    • 基本概念和高級主題
  • 曼寧(Manning)發(fā)布:
    • 自2017年賽事開始提供搶先體驗
  • 訂閱我的時事通訊以保持關(guān)注。 (甚至可以偷看。)

直到4月6日:使用代碼mlparlog可獲得 50%的折扣!

解決可選依賴項

模塊解析是這樣的過程:給定初始模塊和可觀察模塊的范圍,該模塊通過解析require子句構(gòu)建模塊圖。 解析模塊時,必須在可觀察模塊的范圍中找到它需要的所有模塊。 如果是,則將它們添加到模塊圖; 否則會發(fā)生錯誤。 重要的是要注意,在解析期間未放入模塊圖中的模塊在以后的編譯或執(zhí)行期間也不可用。

在編譯時,模塊解析處理可選的依賴項,就像常規(guī)依賴項一樣。 但是,在運行時,大多數(shù)情況下會忽略靜態(tài)子句。 當模塊系統(tǒng)遇到一個模塊系統(tǒng)時,它不會嘗試實現(xiàn)它,這意味著它甚至不檢查命名模塊是否存在于可觀察模塊的范圍中。

僅是可選依賴項的模塊在運行時將不可用。

結(jié)果,即使模塊存在于模塊路徑上(或在此情況下位于JDK中),也不會僅僅由于可選的依賴關(guān)系而將其添加到模塊圖中。 僅當它也是要解析的其他模塊的常規(guī)依賴項,或者因為它是使用命令行標志–add-modules顯式添加的,它才會進入圖表。

也許您偶然發(fā)現(xiàn)了“ 大部分都忽略了可選依賴項”這一短語。 為什么大多數(shù)? 嗯,模塊系統(tǒng)要做的一件事是,如果一個可選的依賴關(guān)系使其成為一個圖形,則會添加一個可讀性邊緣。 這樣可以確保如果存在可選模塊,則可以立即訪問其類型。

針對可選依賴項進行編碼

可選依賴項在針對它們編寫代碼時需要多加考慮,因為這是在monitor.statistics使用stats.fancy中的類型但模塊在運行時不存在時發(fā)生的:

Exception in thread "main" java.lang.NoClassDefFoundError:stats/fancy/FancyStatsat monitor.statistics/monitor.statistics.Statistician.<init>(Statistician.java:15)at monitor/monitor.Main.createMonitor(Main.java:42)at monitor/monitor.Main.main(Main.java:22) Caused by: java.lang.ClassNotFoundException: stats.fancy.FancyStats... many more

哎呀。 我們通常不希望我們的代碼這樣做。

一般來說,當當前正在執(zhí)行的代碼引用類型時,Java虛擬機會檢查它是否已經(jīng)加載。 如果不是,它將告訴類加載器執(zhí)行此操作,如果失敗,則結(jié)果為NoClassDefFoundError,該錯誤通常使應(yīng)用程序崩潰或至少從正在執(zhí)行的邏輯塊中失敗。

對于可選的依賴項,我們選擇退出使模塊系統(tǒng)安全的檢查。

這是JAR hell著名的東西,模塊系統(tǒng)希望通過在啟動應(yīng)用程序時檢查聲明的依賴項來克服 。 但是,由于要求使用static,因此我們選擇退出該檢查,這意味著我們最終可能會遇到NoClassDefFoundError。 我們該怎么做呢?

建立的依存關(guān)系

但是,在研究解決方案之前,我們需要查看我們是否確實有問題。 對于uber.lib,如果調(diào)用庫的代碼已經(jīng)使用了類型, 則我們希望僅使用來自可選依賴項的類型,這意味著類加載已成功。

換句話說,調(diào)用uber.lib時,必須存在所有必需的依賴項,否則將無法進行調(diào)用。 因此,我們畢竟沒有問題,也不需要做任何事情。

內(nèi)部依賴

不過,一般情況有所不同。 帶有可選依賴項的模塊很可能會首先嘗試從中加載類,因此NoClassDefFoundError的風(fēng)險非常高。

一種解決方案是確保在訪問依賴項之前,必須對具有可選依賴項的模塊進行所有可能的調(diào)用。 該檢查點必須評估該依賴項是否存在,如果不存在,則將到達它的所有代碼發(fā)送到不同的執(zhí)行路徑。

模塊系統(tǒng)提供了一種檢查模塊是否存在的方法。 我在時事通訊中解釋了如何到達那里以及為什么使用新的stack-walking API ,所以當我說這是可行的方法時,在這里您只需要信任我:

public class ModuleUtils {public static boolean isModulePresent(String moduleName) {return StackWalker.getInstance(RETAIN_CLASS_REFERENCE).walk(frames -> frames.map(StackFrame::getDeclaringClass).filter(declaringClass ->declaringClass != ModuleUtils.class).findFirst().orElse((Class) ModuleUtils.class));.getModule();.getLayer().findModule(moduleName).isPresent();// chain all the methods!}}

(在實際的應(yīng)用程序中,緩存值可能并不總是重復(fù)相同的檢查。)

用“ stats.fancy”之類的參數(shù)調(diào)用此方法將返回該模塊是否存在。 如果使用常規(guī)依賴項的名稱(簡單的require子句)進行調(diào)用,則結(jié)果將始終為true,因為否則模塊系統(tǒng)將無法啟動應(yīng)用程序。 如果使用可選依賴項的名稱(需要static子句)進行調(diào)用,則結(jié)果將為true或false。

如果存在可選的依賴項,則模塊系統(tǒng)將建立可讀性,因此沿著使用模塊中類型的執(zhí)行路徑進行操作是安全的。 如果不存在,選擇這樣的路徑將導(dǎo)致NoClassDefFoundError,因此必須找到其他路徑。

摘要

有時您想針對運行時并不總是存在的依賴關(guān)系編寫代碼。 為了使依賴項的類型在編譯時可用,但在啟動時不強制其存在,模塊系統(tǒng)提供了require靜態(tài)子句。 但是請注意,如果僅以這種方式引用模塊,則在解析期間不會拾取該模塊,并且需要特別注意以確保如果運行時不存在可選依賴項,則代碼不會崩潰。

要了解有關(guān)模塊系統(tǒng)的更多信息,請查看JPMS標簽或獲取我的書《 Java 9模塊系統(tǒng) (帶Manning)》。 如果您對歷史觀點感興趣,請查看Project Jigsaw標簽 。

翻譯自: https://www.javacodegeeks.com/2017/04/optional-dependencies-java-platform-module-system.html

總結(jié)

以上是生活随笔為你收集整理的Java Platform Module系统中的可选依赖项的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。