類加載的過程
類加載的全過程论矾,加載剃允,驗證沛简,準備,解析和初始化這五個階段斥废。
加載
在加載階段椒楣,虛擬機需要完成以下三件事情:
- 通過一個類的全限定名來獲取定義此類的二進制字節(jié)流
- 將這個字節(jié)流所代表的靜態(tài)存儲結構轉換為方法區(qū)的運行時數(shù)據(jù)結構
- 在Java堆中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口
驗證
這一階段的目的是為了確保Class文件的字節(jié)流中包含的信息符合當前虛擬機的要求牡肉,并且不會危害虛擬機自身的安全捧灰。不同的虛擬機對類驗證的實現(xiàn)可能有所不同,但大致上都會完成下面四個階段的檢驗過程:文件格式驗證统锤、元數(shù)據(jù)驗證凤壁、字節(jié)碼驗證和符號引用驗證吩屹。
文件格式驗證
第一階段要驗證字節(jié)流是否符合Class文件格式的規(guī)范跪另,并且能被當前版本的虛擬機處理拧抖。
元數(shù)據(jù)驗證
第二階段是對字節(jié)碼描述的信息進行語義分析,以保證其描述的信息符合Java語言規(guī)范的要求免绿。
字節(jié)碼驗證
第三階段時整個驗證過程中最復雜的一個階段唧席,主要工作是數(shù)據(jù)流和控制流的分析。在第二階段對元數(shù)據(jù)信息中的數(shù)據(jù)類型做完校驗后嘲驾,這階段將對類的方法體進行校驗分析淌哟。這階段的任務是保證被校驗類的方法在運行時不會做出危害虛擬機安全的行為。
符號引用驗證
最后一個階段的校驗發(fā)生在虛擬機將符號引用直接轉化為直接引用的時候辽故,這個轉化動作將在連接的第三個階段-解析階段產生徒仓。符號引用驗證可以看作是對類自身以外(常量池中的各種符號引用)的信息進行匹配性的校驗。
準備
準備階段是正式為類變量分配內存并設置類變量初始值的階段誊垢,這些內存都將在方法區(qū)進行分配掉弛。
解析
解析階段是虛擬機將常量池的符號引用轉換為直接引用的過程。解析動作主要針對類或接口喂走、字段殃饿、類方法、接口方法四類符號引用進行芋肠。
- 類或接口的解析
- 字段解析
- 類方法解析
- 接口方法解析
初始化
前面的類加載過程中乎芳,除了在加載階段用戶應用程序可以通過自定義類加載器參與之外,其余動作完全由Java虛擬機主導和控制帖池。到了初始化階段奈惑,才真正開始執(zhí)行類中定義的Java程序代碼(或者說是字節(jié)碼)。在準備階段睡汹,變量已經(jīng)賦過一次系統(tǒng)要求的初始值肴甸,而在初始化階段,則是根據(jù)程序員通過程序制定的主觀計劃去初始化類變量和其他資源帮孔,或者說初始化階段是執(zhí)行類構造器<clinit>()方法的過程雷滋。
類加載器
類與類加載器
虛擬機設計團隊把類加載階段中的"通過一個類的全限定名來獲取描述此類的二進制字節(jié)流"這個動作放到Java虛擬機外部去實現(xiàn),以便讓程序自己決定如何去獲取所需的類文兢。實現(xiàn)這個動作的代碼模塊被稱為"類加載器"晤斩。
雙親委派模型
站在Java虛擬機的角度講,只存在兩種不同的類加載器:一種是啟動類加載器(Bootstrap ClassLoader)姆坚,這個類加載器使用C++語言實現(xiàn)澳泵,是虛擬機自身的一部分;另外一種就是所有其他的類加載器兼呵,這些類加載器都由Java語言實現(xiàn)兔辅,獨立于虛擬機外部腊敲,并且全部繼承自抽象類java.lang.ClassLoader。從Java開發(fā)人員的角度來看维苔,類加載器還可以分得更細致一些碰辅,絕大部分Java程序都會使用到以下三種系統(tǒng)提供的類加載器:
- 啟動類加載器
- 擴展類加載器
- 應用程序類加載器