解析Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制_第1頁
解析Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制_第2頁
解析Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制_第3頁
解析Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制_第4頁
解析Java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、解析java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制這篇文章主要介紹了 java虛擬機(jī)中類的初始化及加載器的父委托機(jī)制,包括命名空間等深層次的知識點(diǎn)講解,需要的朋友可以參考下連接驗(yàn)證加載準(zhǔn)備初始化解析類的初始化在初始化階段,java虛擬機(jī)執(zhí)行類的初始化語句,為類的靜態(tài)變量賦予初始值。在程序中,都態(tài)變量的初始化有兩種途徑:1 在靜態(tài)變量的聲明處進(jìn)行初始化;2 在靜態(tài)代碼塊中進(jìn)行初始化。沒有經(jīng)過顯式初始化的靜態(tài)變戢將原有的值。一個比較奇怪的例子:package com.mengdd.classloader;class singleton / private static singleton mlns

2、tance = new singleton(); 位置 1/位置1輸出:/ counterl: 1/ counter2: 0public static int counterl;public static int counter2 = 0;private static singleton mlnstance = new singleton(); 位置 2/位置2輸出:/ counterl: 1/ counter2: 1private singleton() counterl+;cou nter2+;public static singleton getlnstantce() return ml

3、nstanee;public class testi public static void main(string args) singleton singleton = singlet on .getl nstan tce();system.out.println(ncounterl: h + singleton.counterl);system.out.println(”counter2: " + singleton.counter2);可見將生成對象的語句放在兩個位置,輸出是不一樣的(相應(yīng)位置的輸出己在程序注釋中標(biāo)明)。這是因?yàn)槌跏蓟Z句是按照順序來執(zhí)行的。靜態(tài)變量的聲明語句,

4、以及靜態(tài)代碼塊都被看做類的初始化語句,java虛擬機(jī)會按照初始化語句在類文件中的先后順序來依次執(zhí)行它們。類的初始化步驟1假如這個類還沒有被加載和連接,那就先進(jìn)行加載和連接。2. 假如類存在直接的父類,并這個父類還沒冇被初始化,那就先初始化直接的父類。3. 假如類屮存在初始化語句,那就依次執(zhí)行這些初始化語句。類的初始化時(shí)機(jī)java程序?qū)︻惖氖褂梅绞娇梢苑譃閮煞N:1. 主動使用2. 被動使用所冇的java虛擬機(jī)實(shí)現(xiàn)必須在每個類或接口被java程序首次主動使用時(shí)才初始化它們。主動使用的六種情況:1. 創(chuàng)建類的實(shí)例。new test();2. 訪問某個類或接口的靜態(tài)變量,或者對該靜態(tài)變量賦值。int

5、b = test.a;test.a = b;3. 調(diào)用類的靜態(tài)方法test.dosomething();4仮射class.forname(/zco m.men gdd.test");5 初始化一個類的了類class parentclass child extends parentpublic static int a = 3;child.a = 4;6java虛擬機(jī)啟動時(shí)被標(biāo)明為啟動類的類java com.mengdd.test除了以上六種情況,其他使用java類的方式都被看作是對類的被動使用,都不會導(dǎo)致類的初始化。接口的特殊性當(dāng)java虛擬機(jī)初始化一個類時(shí),要求它的所冇父類都己經(jīng)被

6、初始化,但是這條規(guī)則并不適用于接口。在初始化一個類時(shí),并不會先初始化它所實(shí)現(xiàn)的接口。在初始化一個接口時(shí),并不會先初始化它的父接口。因此,-個父接口并不會因?yàn)樗淖咏涌诨蛘邔?shí)現(xiàn)類的初始化而初始化,只有當(dāng)程序首次使用特定接口的靜態(tài)變彊時(shí),才會導(dǎo)致該接口的初始化。final類型的靜態(tài)變量final類型的靜態(tài)變量是編譯時(shí)常量還是變量,會影響初始化語句塊的執(zhí)行。如果一個靜態(tài)變量的值是一個編譯時(shí)的常量,就不會對類型進(jìn)行初始化(類的static塊不執(zhí)行):如果一個靜態(tài)變量的值是一個非編譯時(shí)的常量,即只冇運(yùn)行時(shí)會冇確定的初始化值,則就會對這個類型進(jìn)行初始化(類的static塊執(zhí)行)。例子代碼:package

7、com.mengdd.classloader;import java.util.random;class finaltestl public static final int x = 6 / 3; /編譯時(shí)期已經(jīng)可知其值為2,是常量/類型不需耍進(jìn)行初始化static system.out.println(hstatic block in finaltestl");/此段語句不會被執(zhí)行,即無輸出 class finaltest2 static system.out.println(hstatic block in finaltest2u);/會進(jìn)行類的初始化,即靜態(tài)語句塊會執(zhí)行,有輸出

8、public class inittest public static void main(string args) system.out.println(hfinaltestl: h + finaltestl.x);system.out.println(hfinaltest2: " + finaltest2.x);主動使用的歸屬明確性只冇當(dāng)程序訪問的靜態(tài)變量或靜態(tài)方法確實(shí)在當(dāng)前類或當(dāng)前接口小定義時(shí),才可以認(rèn)為是對類或接口的主動使用。package com.mengdd.classloader;class pare nt static int a = 3;static system.

9、out.println(hparent static block11);static void dosomething() system.out.println(hdo something");class child exte nds pare nt static system.out.println(hchild static block11);public class parenttest public static void main (string! args) system.out.println(hchild.a: h + child.a);child.dosomethi

10、 ng();/ child類的靜態(tài)代碼塊沒有執(zhí)行,說明child類沒有初始化/這是因?yàn)橹鲃邮褂玫淖兞亢头椒ǘ际嵌x在parent類中的classloader 類調(diào)用classloader類的loadclass()方法加載一個類,并不是對類的主動使用,不會導(dǎo)致類的初始化。 package com .men gdd.classloader;class cl static system.out.println(hstatic block in clu);public class classloaderlnittest public static void main(string args) thro

11、ws exception classloader loader = classloader.getsystemclassloaderf);class<?> clazz = loader.loadclassccom.mengdd.classloader.cl“);/ loadclass方法加載-個類,并不是對類的主動使用,不會導(dǎo)致類的初始化system.out.pri ntln(” clazz = classforname(”wwwvisal58com .men gdd. classloader. cl“);類加載器的父委托機(jī)制類加載器類加載器用來把類加載到j(luò)ava煨擬機(jī)中。類加載器

12、的類型有兩種類型的類加載器:1jvm自帶的加載器:根類加載器(bootstrap)擴(kuò)展類加載器(extension)系統(tǒng)類加載器(system)2.用戶口定義的類加載器:java.iang.classloader的子類,用戶可以定制類的加載方式。jvm自帶的加載器java虛擬機(jī)自帶了以下兒種加載器。1.根(bootstrap)類加載器:該加載器沒有父加載器。它負(fù)責(zé)加載虛擬機(jī)的核心類庫,如java.lang.*等。根類加載器從系統(tǒng)屬性sun.boot.class.path所指定的h錄中加載類庫。根類加載器的實(shí)現(xiàn)依賴于底層操作系統(tǒng),屬于虛擬機(jī)的實(shí)現(xiàn)的一部分,它并沒有繼承java.iang.clas

13、slo ader類,它是用c+寫的。2.擴(kuò)展(extension)類加載器:它的父加載器為根類加載器。它從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類庫,或者從jdk的安裝目錄的jrelibext子目錄(擴(kuò)展 目錄)下加載類庫,如果把用戶創(chuàng)建的jar文件放在這個目錄下,也會自動由擴(kuò)展類加載器加載。擴(kuò)展類加載器是純java類,是java.iang.classloader類的了類。3系統(tǒng)(system)類加載器:也稱為應(yīng)用類加載器,它的父加載器為擴(kuò)展類加載器。它從壞境變量classpath或者系統(tǒng)屬性java.class.path所指定的li錄中加載類,它是 用戶自定義的類加載器的默認(rèn)父

14、加載器。系統(tǒng)類加載器是純java類,是java.iang.classloader類的子類。注憊:這里的父加載器概念并不是指類的繼承關(guān)系,子加載器不一定繼承了父加載器(英實(shí)是組合的 關(guān)系)。用戶白定義類加載器除了以上虛擬機(jī)自帶的類加載器以外,用戶還可以定制自己的類加載(user-defined class loader)。java提供了抽象類java.lang.classloader,所有用戶自定義的類加載器都應(yīng)該繼承classloader類。類加載的父委托機(jī)制從jdk 1.2版本開始,類的加載過程采用父親委托機(jī)制,這種機(jī)制能更好地保證java平臺的安全。在父委托機(jī)制中,除了 java虛擬機(jī)自帶

15、的根類加載器以外,其余的類加載器都冇h只冇一個父加載器, 各個加載器按照父子關(guān)系形成了樹形結(jié)構(gòu)。當(dāng)java程序請求加載器loaderl加載sample類時(shí),loaderl首先委托自己的父加載器去加載sample類, 若父加載器能加載,則由父加載器完成加載任務(wù),否則才由loaderl本身加載sample類。說明具體過程的-個例子:ioader2首先從自己的命名空i'可屮查找sample類是否已經(jīng)被加載,如果已經(jīng)加載,就直接返 回代表sample類的class對象的引用。如果sample類還沒有被加載,ioader2首先請求loaderl代為加載,loaderl再請求系統(tǒng) 類加載器代為加載

16、,系統(tǒng)類加載器再請求擴(kuò)展類加載器代為加載,擴(kuò)展類加載器再請求根類 加載器代為加載。若根類加載器和擴(kuò)展類加載器都不能加載,則系統(tǒng)類加載器嘗試加載,若能加載成功, 則將sample類所對應(yīng)的class對象的引用返冋給loaderl, loaderl再返冋給ioader2,從而 成功將sample類加載進(jìn)虛擬機(jī)。若系統(tǒng)加載器不能加載sample類,則loaderl嘗試加載sample類,若loaderl也不能 成功加載,則ioader2嘗試加載。若所有的父加載器及ioader2本身都不能加載,則拋出classnotfoundexception界常。總結(jié)下來就是:每個加載器都優(yōu)先嘗試用父類加載,若父類

17、不能加載則口己嘗試加載;若成功則返回 class對象給子類,若失敗則告訴子類讓子類自己加載。所有都失敗則拋出異常。定義類加載器和初始類加載器若有一個類加載器能成功加載sample類,那么這個類加載器被稱為定義類加載器。所有能成功返回class對象的引用的類加載器(包括定義類加載器,即包括定義類加載器 和它下面的所有子加載器)都被稱為初始類加載器。假設(shè)loaderl實(shí)際加載了 sample類,則loaderl為sample類的定義類加載器,loaded 和loaderl為sample類的初始類加載器。父子關(guān)系需要指出的是,加載器之間的父子關(guān)系實(shí)際上指的是加載器對象之間的包裝關(guān)系,而不 是類之間的

18、繼承關(guān)系。一對父子加載器可能是同一個加載器類的兩個實(shí)例,也可能不是。在子加載器對象屮包裝了一個父加載器對象。例如 loaderl 和 ioader2 都是 myclassloader 類的實(shí)例,并jzl ioader2 包裝了 loaderl, loaderl是ioader2的父加載器。當(dāng)生成一個自定義的類加載器實(shí)例時(shí),如果沒有指定它的父加載器(classloader構(gòu)造方 法無參數(shù)),那么系統(tǒng)類加載器就將成為該類加載器的父加載器。父委托機(jī)制優(yōu)點(diǎn)父親委托機(jī)制的優(yōu)點(diǎn)是能夠提高軟件系統(tǒng)的安全性。因?yàn)樵诖藱C(jī)制下,用戶自定義的類加載器不可能加載應(yīng)該由父加載器加載的可靠類,從 而防止不可靠甚至惡意的代碼代替由父加載器加載的可靠代碼。例如,java.iang.object類總是由根類加載器加載,其他任何用戶自定義的類加載器都不 可能加載含有惡意代碼的java.iang.object類。命名空間每個類加載器都有自己的命名空間,命名空間由該加載器及所有父加載器所加載的類組 成。在同一個命名空間中,不會出現(xiàn)類的完整名字(包括類的包名)相同的兩個類。在不同的命名空間屮,有可能會出現(xiàn)類的完整名字(包括類的包名)相同的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論