類載入過程
類載入過程本質上就是類載入器根據類的全限定名稱去找到對應的class位元組碼文件內容,然後將位元組碼文件的內容載入到虛擬機方法區中的過程。
所以我們大體上可以把類載入的過程分為三部分:
1、載入,就是獲取到class文件的內容
2、鏈接,就是把相應的文件內容添加到虛擬機中,轉變為虛擬機中的class對象,使虛擬機可以使用該類
3、初始化,初始化類對象的中的數據
也就是下面這個樣子

而鏈接其實是一個較為複雜的過程,所以我們把鏈接再拆分成
驗證、準備、解析三個更細粒度的步驟,所以總體的步驟如下圖:

而每個步驟更為詳細的解釋:
1、載入-根據全限定名稱去尋找這個class的位元組碼文件內容,然後根據位元組碼中的內容翻譯成jvm所熟知的class數據結構並保存到記憶體中。
注意這裡的尋找位元組碼文件並不一定局限在傳統的從磁碟中查找,而是非常靈活的,可以來自於db,來自於記憶體,來自於網路,甚至動態生成。
這裡也為class文件的安全存儲提供了保證。
2、驗證-為了防止位元組碼文件存在惡意的資訊,或者有傷害虛擬機的行為,因此需要對位元組碼文件的內容進行一個全面的校驗。包括位元組碼的格式。語義、操作驗證等。
3、準備-為類的靜態變數分配記憶體並賦予對應的默認值。如int 賦予0,對象賦予null,boolean賦予false等。
4、解析-將常量池中的符號引用轉化為直接引用。也就是說將各種對象/方法的符號名稱直接替換為方法區中的指針或者地址偏移量,以便直接調用該對象/方法。
5、初始化-會將所有的靜態變數的值進行一遍初始賦值的操作。同時執行對應的靜態初始化模組。
我們為了方便常常把 驗證、準備、解析是三個步驟統稱為鏈接。而鏈接就是類載入過程中的核心步驟:將位元組碼文件的內容轉化為jvm的運行時環境中可以直接用的過程。
這個過程通常是由虛擬機來完成,我們無法過多干預。但是對於如何進行載入,也就是步驟1中的how,我們可以通過對類載入器進行重載來滿足很多我們需要,這也是類載入過程中,我們能最多干預的地方。(這一部分由於內容比較大而複雜我會在後邊的文章中記錄)
6、使用(防盜連接:本文首發自//www.cnblogs.com/jilodream/ )
7、卸載-對jvm中已經存在的class對象進行卸載。
關於類class對象的卸載條件:
1、該class的任何實例對象都已經被回收了。
2、載入該class文件的classloader也已經被回收了
3、該class文件也不存在任何地方持有他的引用。
也就是說,從目前的角度來看,jvm基本不會再使用到該class文件。此時就可以卸載掉該class對象了
這裡要注意:
1、類的載入前會先載入父類,只有當直接父類載入完畢後,才會擠在當前類。而直接父類的載入又要依託於直接父類的直接父類。依次類推,直至所有類載入完畢。
2、類的載入過程中各步驟的開始是依照前文中的描述。但是為保證更高的效率,各步驟在執行階段則可能會互相交錯執行,如一邊載入一邊鏈接。同時解析階段為了支援jvm的動態綁定(運行時綁定)原因,解析可能會在初始化步驟開始後才開始。
3、類初始化的順序
會先依次執行靜態變數的初始化,接著執行靜態塊的初始化。(如果是構造實例的話,則會接著初始化變數,初始化塊,構造器)

