類從被加載到JVM中開始,到卸載爲止,整個生命週期包括:加載、驗證、準備、解析、初始化、使用和卸載七個階段。指針
類加載的過程:加載->連接->初始化code
加載:簡單的說,類加載階段就是由類加載器負責根據一個類的全限定名來讀取此類的二進制字節流到JVM內部,並存儲在運行時內存區的方法區,而後將其轉換爲一個與目標類型對應的對象實例
加載須要藉助類加載器,在 Java 虛擬機中,類加載器使用了雙親委派模型,即接收到加載請求時,會先將請求轉發給父類加載器。視頻
雙親委派模型:每當一個類加載器接收到加載請求時,它會先將請求轉發給父類加載器。在父類加載器沒有找到所請求的類的狀況下,該類加載器纔會嘗試去加載對象
連接:連接階段要作的是將加載到JVM中的二進制字節流的類數據信息合併到JVM的運行時狀態中,經由驗證、準備和解析三個階段。
即將類合併至 Java 虛擬機中,使之可以執行的過程。接口
(1)驗證 驗證類數據信息是否符合JVM規範,是不是一個有效的字節碼文件,驗證內容涵蓋了類數據信息的格式驗證、語義分析、操做驗證等。 格式驗證:驗證是否符合class文件規範 語義驗證:檢查一個被標記爲final的類型是否包含子類;檢查一個類中的final方法視頻被子類進行重寫;確保父類和子類之間沒有不兼容的一些方法聲明(好比方法簽名相同,但方法的返回值不一樣) 操做驗證:在操做數棧中的數據必須進行正確的操做,對常量池中的各類符號引用執行驗證(一般在解析階段執行,檢查是否經過富豪引用中描述的全限定名定位到指定類型上,以及類成員信息的訪問修飾符是否容許訪問等) (2)準備 爲類中的全部靜態變量分配內存空間,併爲其設置一個初始值(因爲尚未產生對象,實例變量不在此操做範圍內) 被final修飾的靜態變量,會直接賦予原值;類字段的字段屬性表中存在ConstantValue屬性,則在準備階段,其值就是ConstantValue的值 (3)解析 將常量池中的符號引用轉爲直接引用(獲得類或者字段、方法在內存中的指針或者偏移量,以便直接調用該方法),這個能夠在初始化以後再執行。 能夠認爲是一些靜態綁定的會被解析,動態綁定則只會在運行是進行解析;靜態綁定包括一些final方法(不能夠重寫),static方法(只會屬於當前類),構造器(不會被重寫)
初始化:是爲標記爲常量值的字段賦值,以及執行 < clinit > 方法的過程。
只有當初始化完成以後,類才正式成爲可執行的狀態。以蓋房子爲例,只有當房子裝修事後,Tony 才能真正地住進去。
類的初始化僅會被執行一次,這個特性被用來實現單例的延遲初始化。生命週期
那麼,類的初始化什麼時候會被觸發呢?JVM 規範枚舉了下述多種觸發狀況:內存
1.當虛擬機啓動時,初始化用戶指定的主類; 2.當遇到用以新建目標類實例的 new 指令時,初始化 new 指令的目標類; 3.當遇到調用靜態方法的指令時,初始化該靜態方法所在的類; 4.當遇到訪問靜態字段的指令時,初始化該靜態字段所在的類; 5.子類的初始化會觸發父類的初始化; 6.若是一個接口定義了 default 方法,那麼直接實現或者間接實現該接口的類的初始化,會觸發該接口的初始化; 7.使用反射 API 對某個類進行反射調用時,初始化這個類; 8.當初次調用 MethodHandle 實例時,初始化該 MethodHandle 指向的方法所在的類。