fegin需要实现类_深入理解JVM(六)--虚拟机类加载机制
虛擬機把描述類的數據從Class文件加載到內存,并對數據進行校驗、轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制。
類從被加載到虛擬機內存開始,到卸載出內存為止,它的整個生命周期包括:加載、驗證、準備、解析、初始化、使用和卸載七個階段。
類的生命周期1.加載
"加載"是"類加載"這個過程的一個階段,是 “類加載”過程中最先開始進行的操作,加載階段,虛擬機需要完成三件事:
2.驗證
驗證是連接的第一步,這一階段的目的是為了確保Class文件的字節流包含的信息符合當前虛擬機的要求,并且不會危害到虛擬機自身的安全。虛擬機如果不檢查輸入的字節流,對其完全信任的話,很可能會因為載入了有害字節流而導致系統崩潰。
(1)文件格式驗證
檢查字節流是否符合Class文件格式的規范,并且能被當前版本的虛擬機處理:
- 是否以魔數0XCAFEBABE開頭。
- 主、次版本號是否存在當前虛擬機處理范圍內。
- 常量池的常量是否有不被支持的常量類型。
- ... ...
(2)元數據驗證
對字節碼描述的信息進行語義分析,以保證其描述的信息符合Java語言規范的要求:
- 這個類是否有父類。
- 這個類的父類是否繼承了不允許繼承的類。
- 如果這個類不是抽象類,是否實現了其父類或接口之中要求實現的所有方法。
- ... ...
(3)字節碼驗證
(4)符號引用驗證
3.準備
準備階段是正式為類變量分配內存并設置類變量初始值的階段,這些變量所使用的內存都將在方法區中進行分配。
4.解析
解析階段是虛擬機將常量池內的符號引用替換為直接引用的過程。
5.初始化
前面的類加載過程中,除了在加載階段用戶應用程序可以通過自定義類加載器參與之外,其余動作完全由虛擬機主導和控制。到了初始化階段,才真正開始執行類中定義的Java程序代碼。
虛擬機規范嚴格規定了有且只有5種情況必須立即對類進行“初始化”:
(1)遇到new、getstatic、putstatic或invokestatic這4條字節碼指令時,如果類沒有進行過初始化,則需要先觸發其初始化。生成這4條指令的最常見的Java代碼場景是:使用new關鍵字實例化對象的時候、讀取或設置一個類的靜態字段的時候、調用一個類的靜態方法的時候。
(2)使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則需要先觸發其初始化。
(3)當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類初始化。
(4)當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main()方法的類),虛擬機會先初始化這個主類。
(5)當使用JDK1.7的動態語言支持時,如果一個java.lang.invoke.MethodHandle實例最后的解析結果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且這個方法句柄所對應的類沒有進行過初始化,則需要先觸發初始化。
6.類加載器雙親委派模型
從Java虛擬機的角度來說,只存在兩種不同的類加載器:一種是啟動類加載器(Bootstrap ClassLoader),這個類加載器使用C++語言實現(HotSpot虛擬機中),是虛擬機自身的一部分;另一種就是所有其他的類加載器,這些類加載器都有Java語言實現,獨立于虛擬機外部,并且全部繼承自java.lang.ClassLoader。
從開發者的角度,類加載器可以細分為:
啟動類加載器:負責將 Java_Home/lib下面的類庫加載到內存中(比如rt.jar)。由于引導類加載器涉及到虛擬機本地實現細節,開發者無法直接獲取到啟動類加載器的引用,所以不允許直接通過引用進行操作。
擴展類加載器:由sun.misc.Launcher$ExtClassLoader實現。它負責將Java_Home /lib/ext或者由系統變量 java.ext.dir指定位置中的類庫加載到內存中。開發者可以直接使用標準擴展類加載器。
應用程序類加載器:由 sun.misc.Launcher$AppClassLoader實現的。它負責將系統類路徑(CLASSPATH)中指定的類庫加載到內存中。開發者可以直接使用這個類加載器。
除此之外,還有自定義的類加載器,它們之間的層次關系被稱為類加載器的雙親委派模型。該模型要求除了頂層的啟動類加載器外,其余的類加載器都應該有自己的父類加載器,而這種父子關系一般通過組合(Composition)關系來實現,而不是通過繼承(Inheritance)。
類加載器雙親委派模型雙親委派模型的工作原理是,如果一個類加載器收到了類加載請求,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去執行,每一個層次的類加載器都是如此,因此所有的加載請求最終都應該傳送到頂層的啟動類加載器中,只有當父類加載器反饋自己無法完成這個加載請求時,子加載器才會嘗試自己去加載。
優勢:(1)采用雙親委派模式的是好處是Java類隨著它的類加載器一起具備了一種帶有優先級的層次關系,通過這種層級關可以避免類的重復加載,當父親已經加載了該類時,就沒有必要子ClassLoader再加載一次。(2)實現簡單,邏輯清晰易懂。
總結
以上是生活随笔為你收集整理的fegin需要实现类_深入理解JVM(六)--虚拟机类加载机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css初始化样式文件_前端必备技能 we
- 下一篇: 怎么复制黑苹果config配置_估计是最