看完《深刻理解JVM》中關於類加載的一些我的總結,歡迎評論!java
類加載過程:數組
類從被加載到虛擬機內存中開始,到卸載出內存爲止,它的整個生命週期包括:加載、驗證、準備、解析、初始化、使用和卸載七個階段。它們開始的順序以下圖所示:安全
加載->驗證->準備->解析->初始化->使用->卸載數據結構
其中類加載過程:加載、驗證、準備、解析、初始化多線程
加載、驗證、準備、初始化發生的順序是肯定的,而解析階段不必定;線程
在某些狀況能夠在初始化階段以後開始,以支持java的動態綁定對象
(由於類中的方法多是動態綁定)繼承
java綁定:綁定是指把一個方法的調用與方法所在的類關聯;分爲如下兩種方式:遞歸
靜態綁定:在程序執行前方法已經被綁定,java當中的方法只有final,static,private和夠早方法是前期半丁接口
動態綁定:運行時根據具體對象的類型進行綁定,java中全部的方法都是後期綁定;
加載:
加載階段,虛擬機須要完成三件事:
1.經過一個類的全限定名來獲取其定義的二進制字節流;
2.將這個字節流所表明的靜態存儲結構轉化爲方法區的運行時數據結構;
3.在java堆中生成一個表明這個類的java.lang.Class對象,做爲方法區中這些數據的訪問入口;
類加載器:
類加載器不止實現類的加載動做,
啓動類加載器,擴展類加載器,應用程序類加載器,自定義加載器;
若是程序中沒有自定義類加載器,默認的就是應用程序類加載器;
雙親委派模型:
每一次上面的類加載器叫作當前層類加載器的父加載器;使用組合的方式調用父加載器中的代碼;
雙親委派工做流程:
若是一個類加載器收到了類加載的請求,它首先不會本身去嘗試加載這個類,而是把請求委託給父加載器去完成,依次向上,所以,全部的類加載請求最終都應該被傳遞到頂層的啓動類加載器中,只有當父加載器在它的搜索範圍中沒有找到所需的類時,即沒法完成該加載,子加載器纔會嘗試本身去加載該類。
好處:Java類隨着它的類加載器一塊兒具有了帶有優先級的層次關係;一個類只會被一個加載器加載,保證java程序的穩定運行;
驗證:
驗證的目的是爲了確保Class文件中的字節流包含的信息符合當前虛擬機的要求,並且不會危害虛擬機自身安全;
大體都會完成如下四個階段的驗證:
文件格式的驗證,元數據驗證,字節碼驗證,符號引用驗證;
準備:
準備階段是正式爲類變量分配內存並設置類變量初始的階段,這些內存都將在方法區中分配;
需注意:
解析:
解析階段是虛擬機將常量池中的符號引用轉化爲直接引用的過程;
初始化:
初始化是類加載最後一步,此階段才真正開始執行類中定義的java代碼。在準備階段,類變量已經賦過一次系統初始值,初始化階段則根據程序的主觀計劃去初始化類變量和其餘資源;初始化是執行類構造器<clinit>方法的過程;
clinit方法是由編譯器自動收集類中全部類變量的賦值動做和靜態語句塊中的語句合併產生的,靜態語句塊只能訪問到定義在靜態語句塊以前的變量,對於定義在靜態語句塊以後的,只能賦值,不能訪問;
不須要顯示地調用父類構造器,虛擬機保證子類的clinit執行以前父類的clinit已經執行完畢。
若是類中沒有靜態語句塊也沒有對類的賦值操做,JVM能夠不爲這個類生成clinit方法;
執行接口的clinit方法不須要先執行父接口的clinit,只有當父接口中定義的變量唄使用時,父接口才會被初始化;接口實現類初始化時也如此;
虛擬機會保證clinit在多線程環境中被正確的加鎖和同步;