類加載過程
加載->鏈接(驗證,准備,解析)->初始化
1.加載:
利用io從文件系統中讀取.class文件,通過類加載器(classLoader)進字節碼加載到計算機內存中供Jvm使用。
java的四種類加載器(父加載器->子加載器)
1引導類加載器:加載Java 的核心庫
2擴展類加載器:加載java 的擴展庫
3系統類加載器:加載Java 應用的類路徑(CLASSPATH) 自定義的類通過系統類加載器或自定義類加載器加載
4自定義類加載器:開發人員自定義java類加載器
怎么確定使用哪種加載器來加載一個類?
java體系中使用的加載機制是雙親委派模式:
大致流程:加載器如果還有父加載器就將加載交到父加載器加載。
其實真正的加載過程是從1引導類加載器開始加載,加載不了則繼續先下加載。
優點:
1.防止一個類重復加載
2.保證java核心API不會被修改
即使外部重新定義了java核心庫的類(比如Object),但是仍然會被引導類加載器加載而不是系統類加載器加載。
思考:為什么不直接從引導類加載器開始加載?
2.鏈接:
2.1.1驗證
這里驗證的就是后綴名是.class文件,因為我也可以把隨便一個其他后綴名(比如.txt .exe)修改成.class文件
驗證階段可以檢驗是否是合法的class文件,是否有必要加載到內存中
魔數:cafe babe
2.1.2准備
為類中的所有靜態變量分配內存空間,並為其設置一個初始值
被final修飾的靜態變量,會直接賦予原值
2.1.3解析
所謂解析就是指在常量池(jdk1.8從方法區轉移到堆中,方法區更改成元空間)中找到類、接口、方法、字段的符號引用(代碼),並將其替換為直接引用(具體指針)的過程。
3.初始化:
這里執行的是cinit方法,不是執行構造函數方法。
執行所有static方法的代碼,將准備階段static變量進行賦值。
補充一點:
加載階段優先於鏈接階段,但是加載的過程,鏈接階段也在進行。
是一個並發的過程。
鏈接過程在加載過程之后結束。
再補充一點:
當一個類在初始化時,要求其父類全部都已經初始化過了
但是在一個接口初始化時,並不要求父接口完全完成了初始化,只有在真正使用到父接口的時候才會初始化(如引用接口中定義的常量。