溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用Java擴(kuò)展機(jī)制加載所有JAR包

發(fā)布時間:2021-10-29 18:10:45 來源:億速云 閱讀:537 作者:柒染 欄目:編程語言

本篇文章為大家展示了如何使用Java擴(kuò)展機(jī)制加載所有JAR包,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

Java 擴(kuò)展機(jī)制在Java教程中被描述為一種“通過標(biāo)準(zhǔn)可擴(kuò)展的方式來讓Java平臺上所有應(yīng)用使用自定義API”。正如在理解擴(kuò)展機(jī)制進(jìn)行類加載中描述的,“擴(kuò)展框架充分使用了類加載代理機(jī)制”。這種機(jī)制會在rt.jar引導(dǎo)(boot)類加載之后,標(biāo)準(zhǔn)classpath中的類加載之前,加載擴(kuò)展類。

擴(kuò)展目錄的工作機(jī)制在類的加載上與classpath有點(diǎn)類似。對Java應(yīng)用程序來說,所有擴(kuò)展目錄下JAR文件包含的類都可以訪問。然而,會有一些關(guān)鍵的不同點(diǎn)。這些區(qū)別會在下面的文字中高亮顯示。

特征Classpath擴(kuò)展機(jī)制(可選包)
作用域典型的應(yīng)用相關(guān)
  • -classpath/-cp

  • java.class.path

  • 可執(zhí)行JAR Manifest的Class-Path

主機(jī)上所有可能的JRE

  • CLASSPATH環(huán)境變量

所有運(yùn)行在特定JRE上的JVM
  • java.ext.dirs

各種主機(jī)上的JRE

  • Solaris: /usr/jdk/packages/lib/ext

  • Linux: /usr/java/packages/lib/ext

  • Windows: %SystemRoot%\Sun\Java\lib\ext

如何指定.jar文件
  • 明確的通過名字來指定(包括 .jar)

  • 使用通配符來匹配所有的.jar擴(kuò)展

.class Files

  • 指定目錄下的.class文件

所有在指定目錄下的JAR文件都會被加載(即使擴(kuò)展名不是.jar或者沒有擴(kuò)展名)
類加載順序引導(dǎo)和擴(kuò)展類加載之后引導(dǎo)類加載之后,classpath上的類加載之前

一個最重要且值得重視的問題是,擴(kuò)展機(jī)制會找出所有jar格式的文件,即使文件后綴名不是.jar。這意味著,改變classpath中的jar文件后綴名以此逃過通配符的篩選,這種方法在擴(kuò)展目錄中行不通。

我會用一些簡單的例子來展示一些上面提到的區(qū)別。接下來的兩段代碼是一個簡單的HelloWorld類和一個main應(yīng)用程序中的Main類。Main通過調(diào)用main方法來使用HelloWorld類。

HelloWorld.java

public class HelloWorld {    @Override    public String toString()    {       return "Hello, World!";    } }

Main.java

import static java.lang.System.out;   public class Main {    public static void main(final String[] arguments)    {       out.println(new HelloWorld());    } }

為了展示classpath和擴(kuò)展機(jī)制的主要區(qū)別,我將會把編譯過的HelloWorld.class文件歸檔到一個jar包里,命名為HelloWorld.jar。并把它放在一個跟編譯過的Main.class不同的目錄下。

為了展示傳統(tǒng)的classpath的使用,我把HelloWorld.jar放在一個叫做C:\hello的目錄下并且會用通配符訪問JAR來給Main使用。下面的兩個截圖對此進(jìn)行了展示。

如何使用Java擴(kuò)展機(jī)制加載所有JAR包

上面的截圖說明,當(dāng)某個類是在擴(kuò)展目錄下的某個JAR里,Java launcher甚至不需要把HelloWorld.class放到同一個目錄下或者在classpath中指定。這常常被用來說明使用擴(kuò)展機(jī)制的優(yōu)點(diǎn)。因?yàn)樗性谶@個JRE(或者可能是主機(jī)上的所有應(yīng)用)上運(yùn)行的程序都可以不用在classpath上指定就能看到擴(kuò)展目錄下的類。

使用傳統(tǒng)classpath方式——指導(dǎo)應(yīng)用去加載JAR中的類,包含.class文件的JAR文件必須以.jar結(jié)尾。接下來的截圖展示了當(dāng)把在 classpath引用的目錄下的HelloWorld.jar重命名為HelloWorld.backup之后所發(fā)生的事情。

如何使用Java擴(kuò)展機(jī)制加載所有JAR包

***一張截圖展示了,擴(kuò)展目錄下過時的HelloWorld類優(yōu)先于同一目錄下的新定義的HelloWorld類加載。甚至當(dāng)我把當(dāng)前目錄寫進(jìn) classpath中,擴(kuò)展目錄下的舊版本的類仍然優(yōu)先。接下來的圖也同樣展示了擴(kuò)展目錄下的JAR文件“隱藏”了更新的JAR以及其中類的新方法。這些擴(kuò)展目錄下的JAR文件甚至都不是以.jar結(jié)尾的。

<img class="wp-image-13931" src="https://cache.yisu.com/upload/information/20210521/332/448270.jpg" alt="" microsoft yahei'; line-height: 25px;" />

剛剛展示的這個例子,在擴(kuò)展目錄下JAR導(dǎo)致的眾多問題來說不算很復(fù)雜。例子中,至少有一個NoSuchMethodError來提醒這個問 題。一個潛在的更加復(fù)雜的情況是,舊的類有和新類一樣的方法簽名但實(shí)現(xiàn)的方式已經(jīng)過時。在這種情況下,可能沒有錯誤、異?;蛘遲hrowable中任何一種,但是應(yīng)用的邏輯不會像預(yù)期那樣工作。舊的方法可能會一直存在代碼的底層直到被發(fā)現(xiàn)。當(dāng)缺乏單元測試或其他測試時尤其如此。

使用擴(kuò)展目錄會讓開發(fā)人員變得輕松。因?yàn)閿U(kuò)展目錄下JAR文件中的類,可以被所有運(yùn)行在與此擴(kuò)展目錄(如果在操作系統(tǒng)上在主機(jī)范圍內(nèi)啟用擴(kuò)展目錄,那么所有主機(jī)上的JRE都可以訪問)關(guān)聯(lián)JRE上的應(yīng)用訪問。然而,隨意使用擴(kuò)展目錄會有一定的風(fēng)險。你會非常容易忘記擴(kuò)展目錄下過時的類。這會妨礙類加載器選擇明顯應(yīng)當(dāng)被加載的版本。這種情況下,本來應(yīng)該讓開發(fā)者感覺輕松的擴(kuò)展機(jī)制會讓他們非常痛苦。

Elliotte Rusty Harold提對擴(kuò)展機(jī)制有一個警告:“盡管這些看上去很方便,從長遠(yuǎn)來看也是引入了一個隱患,遲早你會從一個你根本沒想過的地方載入一個錯誤的類版本。這會浪費(fèi)你不少時間調(diào)試”。Java教程同樣提出警告(我在這里也著重強(qiáng)調(diào)):“盡管這個機(jī)制擴(kuò)展了平臺的核心API,但是應(yīng)該審慎使用。大部分情況,它是用于像JCP這樣標(biāo)準(zhǔn)化比較好的接口,同時也適用于整個站點(diǎn)的接口”。

盡管擴(kuò)展(可選包)機(jī)制與classpath機(jī)制很像,并且它們都用于部分的類加載,兩者之間的區(qū)別也是非常值得注意的。特別的,記住所有的在擴(kuò)展目錄下的JAR文件(即使它們沒有以.jar結(jié)尾)都會被加載是很重要的。給那些JARs重命名甚至改變他們的文件后綴名都不足以讓類加載器忽略它們。另一方面,使用classpath的時候,重命名classpath中指定的JAR文件會使該JAR無法加載,改變后綴名后,即使在classpath中使用通配符也無法加載所有目錄中的JAR。

一些情況下,擴(kuò)展機(jī)制是比較好的選擇,但是這種情況相當(dāng)少。當(dāng)處理預(yù)期以外的NoSuchMethodErrors問題時,記住擴(kuò)展機(jī)制使很重要的。這樣就會去檢查看看是否問題就出在擴(kuò)展的目錄中。

上述內(nèi)容就是如何使用Java擴(kuò)展機(jī)制加載所有JAR包,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI