ClassLoader主要作用 :將.class後綴的字節碼文件從硬盤上裝載到內存中 ;
1.類加載器深入剖析
Java虛擬機與程序的生命週期 :
當我們執行一個java程序的時候 , 會啓動一個JVM進程 , 當程序執行完之後 , JVM進程就消亡了;
在如下情況下JVM將結束聲明週期 :
- System.exit(int)方法 , 當執行這個方法的時候 , 虛擬機會退出 ; 這個方法傳入一個整形參數 , 這個參數是狀態嗎: 如果這個整形是 0 的話 , 就是正常退出 , 如果不是0的話 , 就是異常退出 ;
- 程序正常結束;
- 程序執行過程中 ,遇到了異常或錯誤 , 而異常終止 : 如果我們在程序中出現了異常 , 而不去處理 , 會將異常一直拋給main函數 ,main函數會將異常拋給JVM , JVM如果處理不了異常 , JVM就會異常退出 ;
- 由於操作系統出現錯誤導致JVM進程終止 : JVM所依賴的平臺出現錯誤 , 導致JVM終止 ;
2.類的加載,連接和初始化
- 加載 :查找並加載類的二進制數據 , 將class字節碼文件加載到內存中 ;
- 連接 :
-驗證 : 確保被加載的類的正確性 , 使用javac編譯工具生成的字節碼文件能通過驗證 , 如果不是由javac編譯生成的字節碼文件 ,如果自己生成的字節碼文件不符合JVM虛擬機對字節碼文件的要求的話 , 可能會出現驗證通不過的情況 ; 比如說隨便拿一個文件 , 將後綴名直接修改爲.class , 這樣的字節碼文件肯定不合法;
-準備 : 爲類的靜態變量分配內存 , 並將其初始化爲默認值;
-解析 : 把類中的符號引用轉爲直接引用 ;- 初始化 :爲類的靜態變量賦予正確的初始值(正確的值指的是用戶賦的值) ;
- -好像這個與連接階段的準備有些重複 , 在連接的準備階段只是賦予初始變量 , 如果用戶給這個變量賦了初始值 ,那麼這個變量在連接的準備階段仍然會賦予初始值 ;
-在這個階段 , 纔會真正的將初始值賦給靜態變量 ;
Java程序對類的使用方式有 主動使用 和被動使用 ;
所有的JVM實現 , 必須在每個類或者接口 , 被java程序 “首次主動使用” 時才初始化他們;
主動使用 :
- 創建類的實例 ;
- 訪問某個類或接口的靜態變量 , 或者對該靜態變量賦值 ;
- 調用類的靜態方法 ;
- 反射 : Class.forName(“類名”) ;
- 初始化一個類的子類 , 看做對父類的主動使用 ;
- java虛擬機啓動的時候 , 被標明啓動類的類 , 即包含main方法的類 , 程序的入口;
除了上面6種主動使用之外 , 其它的情況均爲被動使用 , 其它情況都不會執行第三步初始化 ;
3.類的加載
(1)概念
- 類的加載 : 指的是將類的.class文件中的二進制數據讀入到內存中 , 將其放在運行時數據區的方法區內 , 然後再堆區創建一個java.lang.Class對象 , 用來封裝類在方法區內的數據結構 ;
- 反射 : 反射就是跟句堆區的字節碼文件 , 獲取方法去的數據結構 ;
- 解析 : Class對象是由JVM自己創建的 , 所有的對象都是經過Class對象創建 , 這個Class對象是反射的入口, 通過Class對象 , 可以關聯到目標class字節碼文件的內部結構 ;
所有的類對應的Class對象都是唯一的一個 , 這個類是由JVM進行創建的 , 並且只有JVM纔會創建Class對象;
類加載的最終產品是位於堆區中的Class對象 ,Class對象封裝了類在方法區內的數據結構 , 並且向Java程序員提供了訪問方法區內的數據結構的接口(反射用的接口) ;
(2)加載.class文件的方式
從本地系統中直接加載 : 編譯好的.class字節碼文件直接從硬盤中加載 ;
通過網絡下載.class文件 : 將class字節碼文件放在網絡空間中 , 使用URLClassLoader來加載在網絡上的.class字節碼文件 , 使用默認的父親委託機制加載字節碼文件 ;
從zip ,jar 等壓縮文件中加載字節碼文件 : 在開發的時候 , 導入jar包 , 就是這種方式 ;
從專有的數據庫中提取字節碼文件 ;
將java源文件動態編譯爲字節碼文件 ;
(3)類加載器
l Java虛擬機自帶的類加載器 :
-根類加載器 ( Bootstrap ): 是C++寫的 , 程序員無法再方法獲取到的是一個null值 ;