本文中主要介紹類加載器的工做機制java
一:首先什麼是類加載器?數組
類加載器就是用來加載java類到java虛擬機中。java源程序通過編譯以後造成字節碼文件,類加載器將字節碼文件加載到內存中,並轉換成java.lang.Class的一個實例對象。工具
JVM是基於棧操做的:全部的操做都要通過進棧和出棧操做。基於棧操做的優勢:將運行時的優化工做和執行編譯時優化的執行引擎相結合,從而起到優化Java字節碼的目的。優化
二: 類加載器的做用:this
- 將編譯後的class字節碼文件加載到JVM中。會在加載的過程進行審查每一個類有哪一個類加載器加載?加載哪一個類? 其實是存在一種父級優先的等級結構
- 將字節碼文件從新解析成JVM統一要求的對象格式。
三:類加載器的分類spa
- BootStrap ClassLoader:加載的過程是由JVM自身決定的,具體如何加載,加載哪一個類都是有JVM自身控制的,實際上他並不符合JVM規範,不存在等級結構,沒有父加載 器,也沒有子加載器。他僅僅是做爲一個加載工具存在
- ExtClassLoader:雖然他自己是JVM的一部分,可是加載並非有JVM自身加載,他服務的特定目標是在System.getProperties("java.ext.dirs")目錄下
- APPClassLoader :是ExtClassLoader類加載器的子類,主要加載位於classpath目錄下的類 System.getProperties("java.class.path")
![](http://static.javashuo.com/static/loading.gif)
四:JVM加載字節碼文件的兩種方式線程
- 隱式加載:不調用類加載器,將須要的類自動加載到內存中 例如:當前類須要外部類的引用時,就會觸發隱式加載
- 顯式加載:調用 this.getClass(),this.getClassLoader(),Class.forName(class)等方式完成的加載就是顯式加載
兩種加載方式能夠混合使用,顯式加載自定義的類,若是該類中有其餘類的引用,就會觸發隱式加載。指針
![](http://static.javashuo.com/static/loading.gif)
五:類加載常見的錯誤分析對象
- ClassNotFoundException:顯式加載字節碼文件時,找不到對應的字節碼文件異常,發生這種問題的緣由是在對應的classpath下可能沒有對應的字節碼文件,致使異常的發生;解決方案:到對應的classpath下面檢查是否有對應的字節碼文件,經過this.getClass().getClassLoader().getResources().toString();得到path的路徑
- NotClassDefFoundError:類不存在異常 產生的緣由是:new關鍵字,引用類,繼承接口或者類,方法參數用有引用,這些都會致使此種異常的發生。在隱式加載這些類時可能出現類不存在的異常。
- ClassCastException:強制類型轉換時出現這個錯誤
在JVM進行類型轉換時會進行自動檢查 blog
- 普通對象:必須是目標類的實例對象或者子類對象;若是是接口,對象是該接口的子類對象
- 數組對象:目標類必須是數組類型或者java.lang包下的Object ,Clonable,java.io包下的Serializable
解決類型轉換異常的方法:顯式指明對象類型;經過instanceof判斷是不是目標對象類型,而後在進行類型轉換。
六:JVM的體系結構以及工做方式
- JVM是經過模擬真實計算機,從而達到一個真實計算機所具備的計算功能的體系結構。以計算機爲中心的真實計算機的體系結構
- 指令集:計算機可以識別的機器語言的全部命令集合
- 計算單元:可以識別而且控制指令執行的功能模塊
- 寄存器:中央處理器的核心組件,用來暫存,指令,地址和數據
- 存儲單元:可以存儲計算機操做數和操做結構的單元,例如:內存和磁盤
- 尋址方式:地址的範圍,最小地址和最大地址範圍以及地址的運行規則
- JVM的體系結構:
- 執行引擎:至關於CPU,控制指令執行。解析字節碼文件,獲得解析結果。
- pc寄存器:每一個線程啓動的時候都會建立一個pc寄存器。寄存器中保存的是當前執行的JVM指令的地址。保存下一條將要執行的指令地址的寄存器是:pc寄存器。他老是保存着下一條將要執行的指令地址。地址能夠是一個本地指針,也能夠是方法中相對於方法起始指令的地址。
- 本地方法棧:保存native方法的區域
- 堆:保存的是建立的對象實例。全部的類對象都是經過new建立,建立對象後會在棧中建立該對象的引用。
- 方法區:又叫作靜態區:保存的是方法數據,類,靜態變量,靜態方法,常量和成員方法
- 運行時常量池:存放的是類和接口的常量,除此以外,還有成員方法和成員變量的引用。JVM運行時就是經過這些引用來找到實際的地址
![](http://static.javashuo.com/static/loading.gif)