類的加載
-
加載機制
虛擬機把描述類的數據從class文件加載到內存,並對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型。有以下3點機制
1、 全盤負責機制,當一個類加載器負責加載某個Class時,該Class所依賴的和引用的其他Class也將由該類加載器負責載入,除非顯示使用另外一個類加載器來載入
2、 父類委託,也叫雙親委派機制。先讓父類加載器試圖加載該類,只有在父類加載器無法加載該類時才嘗試從自己的類路徑中加載該類
3、 緩存機制,緩存機制將會保證所有加載過的Class都會被緩存,當程序中需要使用某個Class時,類加載器先從緩存區尋找該Class,只有緩存區不存在,系統纔會讀取該類對應的二進制數據,並將其轉換成Class對象,存入緩存區。這就是爲什麼修改了Class後,必須重啓JVM,程序的修改纔會生效
-
加載過程
1、加載
- 通過一個類的全限定名來獲取其定義的二進制字節流。
- 將這個字節流所代表的靜態存儲結構轉化爲方法區的運行時數據結構。
- 在Java堆中生成一個代表這個類的java.lang.Class對象,作爲對方法區中這些數據的訪問入口
2、 連接
連接分爲以下三個步驟
-
驗證
校驗class文件包含的信息是否符合jvm的規範。具體的校驗通過對文件格式,元數據,字節碼,符號引用驗證來完成
-
準備
爲類變量分配內存,並將其初始化爲默認值
1、這時候進行內存分配的僅包括類變量(static),而不包括實例變量,實例變量會在對象實例化時隨着對象一塊分配在Java堆中。
2、這裏所設置的初始值通常情況下是數據類型默認的零值(如0、0L、null、false等),而不是被在Java代碼中被顯式地賦予的值
-
解析
類型中的符號引用轉換成爲直接引用。解析動作主要針對類或接口、字段、類方法、接口方法、方法類型、方法句柄和調用點限定符7類符號引用進行
3、 初始化
-
執行類的構造器方法的過程。
-
類初始化時機:只有當對類的主動使用的時候纔會導致類的初始化,類的主動使用包括以下六種:
1、創建類的實例,也就是new的方式
2、訪問某個類或接口的靜態變量,或者對該靜態變量賦值
3、調用類的靜態方法
4、反射(如 Class.forName(“xxx.xxx.xxxClass”))
5、初始化某個類的子類,則其父類也會被初始化
6、Java虛擬機啓動時被標明爲啓動類的類( JavaTest),直接使用 java.exe命令來運行某個主類
4、使用
完成類的初始化後,就可以對類進行實例化
5、卸載
當代表類的class對象不在被引用時,class對象就會結束生命週期,類在方法區內的數據就會被卸載
-
類加載器
啓動類加載器: BootstrapClassLoader,負責加載jdk基本庫,如rt.jar中的類(java開頭的類)。啓動類加載器是無法被Java程序直接引用的。擴展類加載器: ExtensionClassLoader,負責加載擴展庫,如ext中的類(javax開頭的類),開發者可以直接使用擴展類加載器。
應用程序類加載器: ApplicationClassLoader,負責加載用戶類路徑(ClassPath)所指定的類,開發者可以直接使用該類加載器,如果應用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。