偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

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

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

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

 

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

所有運(yùn)行在特定JRE上的JVM

 

各種主機(jī)上的JRE

  • Solaris: /usr/jdk/packages/lib/ext
  • Linux: /usr/java/packages/lib/ext
  • Windows: %SystemRoot%\Sun\Java\lib\ext
如何指定 .jar文件

 

  • 明確的通過(guò)名字來(lái)指定(包括 .jar)
  • 使用通配符來(lái)匹配所有的.jar擴(kuò)展

.class Files

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

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

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

HelloWorld.java

  1. public class HelloWorld 
  2.    @Override 
  3.    public String toString() 
  4.    { 
  5.       return "Hello, World!"
  6.    } 

Main.java

  1. import static java.lang.System.out; 
  2.   
  3. public class Main 
  4.    public static void main(final String[] arguments) 
  5.    { 
  6.       out.println(new HelloWorld()); 
  7.    } 

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

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


以上兩個(gè)截圖說(shuō)明,盡管我刪掉了當(dāng)前目錄下的HelloWorld.class,Java 主應(yīng)用仍然能加載它。這是因?yàn)?a rel="nofollow" target="_blank">Java launcher被告知(通過(guò)-classpath這個(gè)可選參數(shù))去C:\hello目錄下尋找。使用擴(kuò)展機(jī)制,不需要把類(lèi)放到當(dāng)前目錄或者指定到 classpath下就可以加載。接下來(lái)的截圖展示了這一點(diǎn)。

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

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

上面這張圖展示了當(dāng)classpath引用的目錄下JAR文件沒(méi)有以.jar結(jié)尾時(shí)發(fā)生的NoClassDefFoundError異常??赡苡悬c(diǎn)令人驚訝,擴(kuò)展機(jī)制不是這樣工作的。所有在擴(kuò)展目錄下的JAR文件,不管后綴名是什么甚至沒(méi)有后綴名都會(huì)被加載。接下來(lái)的截圖展示了這一點(diǎn)。

這張圖展示了,給在擴(kuò)展目錄中的JAR文件重命名為沒(méi)有后綴的文件并不妨礙類(lèi)加載器加載JAR文件中的類(lèi)。換句話(huà)說(shuō),類(lèi)加載機(jī)制是通過(guò)文件類(lèi)型而不是文件名或后綴來(lái)加載所有在擴(kuò)展目錄中的JAR文件的。正如可選包(Optional Package)概覽所總結(jié)的,“JAR文件本身沒(méi)有什么特別的地方,其中包含的class文件也沒(méi)有讓JAR成為已安裝過(guò)的可選包。只有位于jre/lib/ext下,才可能讓JAR成為已安裝的可選包。”

在擴(kuò)展目錄中放包含太多類(lèi)定義的JAR會(huì)有一些風(fēng)險(xiǎn)和負(fù)面效果。例如,當(dāng)我們看到classpath中所指定的類(lèi)方法存在,還報(bào)出NoSuchMethodErrors異常,會(huì)令人非常惱火。這是我以前寫(xiě)過(guò)眾多可以導(dǎo)致NoSuchMethodError問(wèn)題的其中一個(gè)。但是忘記擴(kuò)展目錄下JAR文件中的過(guò)時(shí)(outdated)和廢棄的(obsolete)類(lèi)是另一個(gè)潛在的原因。接下來(lái)會(huì)展示這一點(diǎn)。

接下來(lái)的兩段代碼展示了Main.java和HelloWorld.java修改后的版本。特別要注意的是,HelloWorld有一個(gè)全新的方法,這個(gè) 方法會(huì)被新版本的Main調(diào)用。在這個(gè)例子中,我會(huì)把新編譯的HelloWorld.class文件和Main放在同一個(gè)目錄下。這樣當(dāng)我運(yùn)行Main 的時(shí)候,就能證明擴(kuò)展目錄下的JAR中過(guò)時(shí)的類(lèi)會(huì)比當(dāng)前目錄下的新類(lèi)優(yōu)先加載。

修改后的Hello World.java(新方法)

  1. public class HelloWorld 
  2.    @Override 
  3.    public String toString() 
  4.    { 
  5.       return "Hello, World!"
  6.    } 
  7.   
  8.    public String directedHello(final String name) 
  9.    { 
  10.       return "Hello, " + name; 
  11.    } 

修改后的Main.java

  1. import static java.lang.System.out; 
  2.   
  3. public class Main 
  4.    public static void main(final String[] arguments) 
  5.    { 
  6.       final HelloWorld helloWorld = new HelloWorld(); 
  7.       out.println(helloWorld); 
  8.       out.println(helloWorld.directedHello("Dustin")); 
  9.    } 

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

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

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

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

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

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

原文鏈接: marxsoftware 翻譯: ImportNew.com 孟 冰川

譯文鏈接: http://www.importnew.com/13919.html

責(zé)任編輯:張偉 來(lái)源: ImportNew
相關(guān)推薦

2021-06-02 06:01:31

Java擴(kuò)展Jar包

2021-10-05 22:09:31

Jar加載機(jī)制

2023-10-19 09:14:34

Java開(kāi)發(fā)

2024-08-09 08:46:00

Springjar 包YAML

2015-09-24 08:55:14

Java動(dòng)態(tài)代理擴(kuò)展

2015-09-24 08:54:36

java動(dòng)態(tài)代理

2021-07-05 06:51:43

Java機(jī)制類(lèi)加載器

2010-04-21 09:26:54

Java動(dòng)態(tài)代理

2009-06-04 10:36:11

struts2 jar

2009-09-24 09:44:32

Hibernate j

2010-07-07 18:34:43

UML公共機(jī)制

2017-09-20 08:07:32

java加載機(jī)制

2025-05-08 03:25:00

DubboSPI機(jī)制

2023-05-10 11:07:18

2017-03-08 10:30:43

JVMJava加載機(jī)制

2009-06-10 20:44:18

netbeans 打包JAR文件

2025-07-01 07:41:37

Java類(lèi)加載器雙親委派

2023-10-31 16:00:51

類(lèi)加載機(jī)制Java

2009-02-03 09:42:53

JAVA類(lèi)JVM指令forName方法

2025-06-18 07:32:16

SpringJar動(dòng)態(tài)加載
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)