資源描述:
《java類加載過程詳解》由會員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫。
1、類(型)的生命周期--裝載、連接、初始化、卸載??2009-02-1413:04:54
2、??分類:Java
3、字號?訂閱?Java虛擬機(jī)通過裝載、連接和初始化一個Java類型,使該類型可以被正在運(yùn)行的Java程序所使用。?1.??????裝載?裝載階段包括三個基本動作:?a)????????通過該類型的完全限定名,產(chǎn)生一個代表該類型的二進(jìn)制數(shù)據(jù)流。b)????????解析這個二進(jìn)制數(shù)據(jù)流為方法區(qū)的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(方法區(qū))c)????????創(chuàng)建一個表示該類型的java.lang.Class類的實(shí)例(堆上)?
4、二進(jìn)制數(shù)據(jù)的產(chǎn)生的可能是很多的,比如:從本地系統(tǒng)裝載一個class文件、網(wǎng)絡(luò)下載一個class文件等等,有了這些二進(jìn)制數(shù)據(jù)之后,java虛擬機(jī)就會對這些數(shù)據(jù)進(jìn)行足夠的處理,然后它才能創(chuàng)建java.lang.Class的實(shí)例對象。?裝載步驟的最終產(chǎn)品就是這個Class類的實(shí)例對象,它成為Java程序與內(nèi)部數(shù)據(jù)結(jié)構(gòu)之間的接口。要訪問關(guān)于該類型的信息,程序就要調(diào)用該類型對應(yīng)的Class對應(yīng)的方法。?這樣一個過程就是把一個二進(jìn)制數(shù)據(jù)解析為方法區(qū)中的內(nèi)部數(shù)據(jù)結(jié)構(gòu)、并在堆上建立一個Class對象的過程,稱為“創(chuàng)建”
5、類型。2.??????連接在類型被裝載以后,就準(zhǔn)備連接了。連接過程的第一步就是:驗(yàn)證?2.1驗(yàn)證在裝載過程中,虛擬機(jī)必須解析代表類型的二進(jìn)制數(shù)據(jù)流,并且構(gòu)造內(nèi)部數(shù)據(jù)結(jié)構(gòu),這時候就必須做一些特定的檢查,以保證解析二進(jìn)制數(shù)據(jù)的初始工作不會導(dǎo)致虛擬機(jī)崩潰。比如確保每一個部分在正確的位置,擁有正確的長度,驗(yàn)證文件不是太長或者太短,等等,雖然這些檢查在裝載期間完成,是在正式連接驗(yàn)證之前完成,但是它們在邏輯上仍然屬于驗(yàn)證階段。?在正式的驗(yàn)證階段可能需要完成一下檢查:?l?檢查final的類不能擁有子類l?檢查fin
6、al的方法不能被覆蓋l?確保在類型和超類型之間沒有不兼容的方法聲明l?檢查所有常量池入口相互之間一致l?檢查常量池中所有的特殊字符串l?檢查字節(jié)碼完整性?上面列出的最復(fù)雜的任務(wù)就是:字節(jié)碼完驗(yàn)證。所有的Java需以及都必須設(shè)法為它們執(zhí)行的每一個方法檢查字節(jié)碼的完整性。?2.2準(zhǔn)備?在準(zhǔn)備階段,Java虛擬機(jī)為類變量分配內(nèi)存,設(shè)置默認(rèn)初始值。但在到達(dá)初始化之前,類變量都沒有被初始化為真正的初始值(準(zhǔn)備階段不執(zhí)行Java代碼)。?2.3解析?解析過程就是在類型的常量池中尋找類、接口、字段和方法的符號引用,把
7、這些符號引用替換成直接引用的過程。?3.??????初始化?初始化就是為類變量賦予正確的初始值。?3.1初始化的時機(jī)-------在首次主動使用前初始化?在類和接口被裝載和連接上,Java虛擬機(jī)規(guī)范提供了一定的靈活性。但是它嚴(yán)格地定義了初始化的時機(jī)。所有的Java虛擬機(jī)實(shí)現(xiàn)必須在每個類或接口首次主動使用時初始化。下面6種情況符合主動使用的要求:?l?當(dāng)創(chuàng)建某個類的新實(shí)例時(new;或者不明確的創(chuàng)建。反射??寺』蛘叻葱蛄谢﹍?調(diào)用某個類的靜態(tài)方法l?使用某個類或接口的靜態(tài)字段,或者對該字段賦值(fina
8、l修飾的除外,它被初始化為一個編譯時的常量表達(dá)式)l?調(diào)用JavaAPI中的某些反射方法l?當(dāng)初始化某個類的子類時(要求超類也已經(jīng)初始化)l?當(dāng)虛擬機(jī)啟動時某個被表明為啟動類的類(main()方法那個類)?除了上述6種情況以外,所有其他使用Java類型的方式都是被動使用。它們都不會導(dǎo)致Java類型的初始化。?對于第三點(diǎn),使用一個非常量的靜態(tài)字段只有當(dāng)類或者接口的確使用了這個字段時才是主動使用。?比如,類中聲明的字段可能會被子類引用;接口中聲明的字段可能會被子接口或者實(shí)現(xiàn)了這個接口的類引用,對于子類、子接
9、口和實(shí)現(xiàn)了接口的類來說,這就是被動使用------使用它們并不會觸發(fā)它們的初始化。只有當(dāng)字段的確是被類或者接口聲明的時候才是主動使用。?當(dāng)然,超類和子類的規(guī)則對于接口并不適用,一個接口的初始化不要求它的父接口預(yù)先被初始化。只有在某個接口所聲明的非常量字段被使用時,該接口才會被初始化,而不是因?yàn)檫@個接口的子接口或類要初始化而被初始化。?無論如何,如果一個類型在它的首次使用之前還沒有被裝載和連接的話,那它必須不在此時被裝載和連接,這樣它才能被初始化。裝載、連接可以在更早的時候進(jìn)行。??3.2初始化初探?為類
10、變量賦予正確的初始值是通過:類變量初始化語句或者靜態(tài)初始化語句給出的。?一個類變量初始化語句是變量聲明后面的等號和表達(dá)式:?classExample1a{//"=3*(int)(Math.random()*5.0)"istheclassvariable//initializerstaticintsize=3*(int)(Math.random()*5.0);}??靜態(tài)初始化語句是一個以static關(guān)鍵字開頭的程序快:classExample