您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何使用Java擴展機制加載所有JAR包,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
Java 擴展機制在Java教程中被描述為一種“通過標準可擴展的方式來讓Java平臺上所有應用使用自定義API”。正如在理解擴展機制進行類加載中描述的,“擴展框架充分使用了類加載代理機制”。這種機制會在rt.jar引導(boot)類加載之后,標準classpath中的類加載之前,加載擴展類。
擴展目錄的工作機制在類的加載上與classpath有點類似。對Java應用程序來說,所有擴展目錄下JAR文件包含的類都可以訪問。然而,會有一些關鍵的不同點。這些區別會在下面的文字中高亮顯示。
特征 | Classpath | 擴展機制(可選包) |
---|---|---|
作用域 | 典型的應用相關
主機上所有可能的JRE
| 所有運行在特定JRE上的JVM
各種主機上的JRE
|
如何指定 | .jar文件
.class Files
| 所有在指定目錄下的JAR文件都會被加載(即使擴展名不是.jar或者沒有擴展名) |
類加載順序 | 引導和擴展類加載之后 | 引導類加載之后,classpath上的類加載之前 |
一個最重要且值得重視的問題是,擴展機制會找出所有jar格式的文件,即使文件后綴名不是.jar。這意味著,改變classpath中的jar文件后綴名以此逃過通配符的篩選,這種方法在擴展目錄中行不通。
我會用一些簡單的例子來展示一些上面提到的區別。接下來的兩段代碼是一個簡單的HelloWorld類和一個main應用程序中的Main類。Main通過調用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和擴展機制的主要區別,我將會把編譯過的HelloWorld.class文件歸檔到一個jar包里,命名為HelloWorld.jar。并把它放在一個跟編譯過的Main.class不同的目錄下。
為了展示傳統的classpath的使用,我把HelloWorld.jar放在一個叫做C:\hello的目錄下并且會用通配符訪問JAR來給Main使用。下面的兩個截圖對此進行了展示。
上面的截圖說明,當某個類是在擴展目錄下的某個JAR里,Java launcher甚至不需要把HelloWorld.class放到同一個目錄下或者在classpath中指定。這常常被用來說明使用擴展機制的優點。因為所有在這個JRE(或者可能是主機上的所有應用)上運行的程序都可以不用在classpath上指定就能看到擴展目錄下的類。
使用傳統classpath方式——指導應用去加載JAR中的類,包含.class文件的JAR文件必須以.jar結尾。接下來的截圖展示了當把在 classpath引用的目錄下的HelloWorld.jar重命名為HelloWorld.backup之后所發生的事情。
***一張截圖展示了,擴展目錄下過時的HelloWorld類優先于同一目錄下的新定義的HelloWorld類加載。甚至當我把當前目錄寫進 classpath中,擴展目錄下的舊版本的類仍然優先。接下來的圖也同樣展示了擴展目錄下的JAR文件“隱藏”了更新的JAR以及其中類的新方法。這些擴展目錄下的JAR文件甚至都不是以.jar結尾的。
<img class="wp-image-13931" src="https://cache.yisu.com/upload/information/20210521/332/448270.jpg" alt="" microsoft yahei'; line-height: 25px;" />
剛剛展示的這個例子,在擴展目錄下JAR導致的眾多問題來說不算很復雜。例子中,至少有一個NoSuchMethodError來提醒這個問 題。一個潛在的更加復雜的情況是,舊的類有和新類一樣的方法簽名但實現的方式已經過時。在這種情況下,可能沒有錯誤、異常或者throwable中任何一種,但是應用的邏輯不會像預期那樣工作。舊的方法可能會一直存在代碼的底層直到被發現。當缺乏單元測試或其他測試時尤其如此。
使用擴展目錄會讓開發人員變得輕松。因為擴展目錄下JAR文件中的類,可以被所有運行在與此擴展目錄(如果在操作系統上在主機范圍內啟用擴展目錄,那么所有主機上的JRE都可以訪問)關聯JRE上的應用訪問。然而,隨意使用擴展目錄會有一定的風險。你會非常容易忘記擴展目錄下過時的類。這會妨礙類加載器選擇明顯應當被加載的版本。這種情況下,本來應該讓開發者感覺輕松的擴展機制會讓他們非常痛苦。
Elliotte Rusty Harold提對擴展機制有一個警告:“盡管這些看上去很方便,從長遠來看也是引入了一個隱患,遲早你會從一個你根本沒想過的地方載入一個錯誤的類版本。這會浪費你不少時間調試”。Java教程同樣提出警告(我在這里也著重強調):“盡管這個機制擴展了平臺的核心API,但是應該審慎使用。大部分情況,它是用于像JCP這樣標準化比較好的接口,同時也適用于整個站點的接口”。
盡管擴展(可選包)機制與classpath機制很像,并且它們都用于部分的類加載,兩者之間的區別也是非常值得注意的。特別的,記住所有的在擴展目錄下的JAR文件(即使它們沒有以.jar結尾)都會被加載是很重要的。給那些JARs重命名甚至改變他們的文件后綴名都不足以讓類加載器忽略它們。另一方面,使用classpath的時候,重命名classpath中指定的JAR文件會使該JAR無法加載,改變后綴名后,即使在classpath中使用通配符也無法加載所有目錄中的JAR。
一些情況下,擴展機制是比較好的選擇,但是這種情況相當少。當處理預期以外的NoSuchMethodErrors問題時,記住擴展機制使很重要的。這樣就會去檢查看看是否問題就出在擴展的目錄中。
上述內容就是如何使用Java擴展機制加載所有JAR包,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。