類加載器子系統
![](http://static.javashuo.com/static/loading.gif)
做用
- 負責從文件系統或網絡系統中加載class文件,class文件在開頭有特殊的標記(魔術開頭CA FE BA BE)
- ClassLoader只負責加載class文件,至於可否運行,由執行引擎決定
- 加載的類的信息存放於一塊稱爲方法區的內存空間。除了類的信息外,方法區中還會存放運行時常量池信息,可能還包括字符串字面量和數字常量(這部分常量信息是Class文件中常量池部分的內存映射)
類加載過程
![](http://static.javashuo.com/static/loading.gif)
加載
- 經過一個類的全限定類名獲取定義此類的二進制字節流
- 將這個字節碼所表明的靜態存儲結構轉化爲方法區的運行時數據
- 在內存中生成一個表明這個類的java.lang.Class對象,做爲方法區這個類的各類數據訪問入口
![](http://static.javashuo.com/static/loading.gif)
連接
驗證
- 目的在於肯定class文件的字節流中包含信息符合當前虛擬機要求,保證被加載類的正確性,不會危害虛擬機自身安全
- 主要包括四種驗證,文件格式驗證,元數據驗證,字節碼驗證,符號引用驗證
- 文件格式驗證主要驗證魔術開頭(CAFE BABE),常量池中常量的類型、版本號等
- 元數據驗證:這個類是否有父類,Object類除外,是否繼承final類
準備
爲類變量分配內存,並設置類變量初始值,基本類型爲默認值,引用類型爲nulljava
這裏不包含final修飾的static變量,由於final修飾的變量在編譯的時候就會分配好默認值,準備階段會顯式初始化bootstrap
準備階段不會爲實例化變量初始化,類變量分配在方法區中,實力變量分配在Java堆中安全
解析
將常量池內的符號引用轉換爲直接引用的過程網絡
事實上,解析操做每每會伴隨着JVM在執行完初始化以後再執行多線程
符號引用就是一組符號來描述所引用的目標。符號引用的字面量形式明肯定義在《java虛擬機規範》的class文件格式中。直接引用就是直接指向目標的指針、相對偏移量或一個間接定位到目標的句柄編輯器
解析動做主要針對類或接口、字段、類方法、接口方法、方法類型等。對應常量池中的CONSTANT Class info、CONSTANT Fieldref info、CONSTANT Methodref info等spa
初始化
類的初始化時機
一、建立類的實例
二、訪問某個類或者接口的靜態變量,或者對該靜態變量複製
三、調用類的靜態方法
四、反射 Class.forName("com.chaoba.Test")
五、初始化一個類的子類
六、java虛擬機啓動時被標記爲啓動的類
七、JDK7開始提供的動態語言支持:java.lang.invoke.MethodHandle實例的解析結果REF_getStatic、REF putStatic、REF_invokeStatic句柄對應的類沒有初始化,則初始化
除了以上七種狀況,其餘使用Java類的方式都被看做是對類的被動使用,都不會致使類的初始化,即不會執行初始化階段(不會調用 clinit() 方法和 init() 方法)線程
- 初始化階段就是執行類構造器
()方法的過程
- 此方法不須要被定義,是javac編輯器自動收集類中的全部類變量的賦值動做和靜態代碼塊中的語句合併而來
- 構造器方法中指令按語句在源文件中出現的順序執行
-
()不一樣於類的構造器(關聯:構造器是虛擬機視角下的
())
- 若該類具備父類,則應該先執行父類的構造方法
- 虛擬機必須保證一個類的
()在多線程環境下被同步加鎖
類加載器的分類
引導類加載器(Bootstrap ClassLoader)
- 加載Java的核心庫(JAVA_HOME/jre/lib/rt.jar、resources.jar或sun.boot.class.path路徑下的內容),用於提供JVM自身須要的類
- 沒有繼承自ClassLoader類,沒有父加載器
- 加載擴展類和應用程序類加載器,並做爲他們的父類加載器
- 出於安全考慮,Bootstrap啓動類加載器只加載包名爲java、javax、sun等開頭的類
擴展加載器
- 父類爲引導類加載器
- Java語言編寫,由sun.misc.Launcher$ExtClassLoader實現
- 從java.ext.dirs系統屬性所指定的目錄中加載類庫,或從JDK的安裝目錄的jre/lib/ext子目錄(擴展目錄)下加載類庫。若是用戶建立的JAR放在此目錄下,也會自動由擴展類加載器加載
應用加載器(系統加載器)
- 系統類加載器是全局惟一的
- Java語言編寫,由sun.misc.LaunchersAppClassLoader實現
- 負責加載環境變量classpath或系統屬性java.class.path指定路徑下的類庫
- 該類加載是程序中默認的類加載器,通常來講,Java應用的類都是由它來完成加載
- 經過classLoader.getSystemclassLoader()方法能夠獲取到該類加載器
自定義類加載器(User-Defined ClassLoader)
- 父類爲應用加載器
- 將全部派生於抽象類ClassLoader的類加載器都劃分爲自定義類加載器
雙親委派機制
![](http://static.javashuo.com/static/loading.gif)
Java虛擬機對class文件採用的是按需加載的方式,也就是說當須要使用該類時纔會將它的class文件加載到內存生成class對象。並且加載某個類的class文件時,Java虛擬機採用的是雙親委派模式,即把請求交由父類處理,它是一種任務委派模式3d
優點
- 避免類的重複加載
- 保護程序安全,防止核心API被隨意篡改
沙箱安全機制
![](http://static.javashuo.com/static/loading.gif)
其餘
![](http://static.javashuo.com/static/loading.gif)