java jvm 加载_Jvm是如何加载Java类的?
前言
我們知道Java語言的類型可以分為兩大類:基本類型「primitive types」和引用類型「reference types」.
對于Java的基本數據類型是Java虛擬機定義好的.至于另一大類「引用數據類型」, Java將其分為四種類型:類
接口
數組
泛型參數
由于「泛型參數」在編譯時期會被擦除, 因此Java虛擬機的類型實際上只有三種.
在類、接口、數組當中,「數組」是由Java虛擬機直接生成的, 類、接口則有對應的「字節流」.
最常見的字節流則屬于由Java編譯器生成的「class」文件.除此之外我們還可以在程序內部生成、直接從網絡當中獲取(如applet)的字節流.
這此不同形式的「字節流」都會被加載到Java虛擬機中, 成為類或者接口.
加載過程
從.class文件中的類到內存里的類, 按先后順序需要經過加載、鏈接、初始化三個過程.
其中「鏈接過程」當中還需要進行驗證.
內存中的類沒有經過初始化,同樣是不能能使用.
加載
「查找」是為了查找字節流,并且據此創建類的過程.對于數組來說,是沒有字節流的,而是由Java虛擬機直接生成的對于其它類型來說, Java虛擬機則需要借助類加載器來完成查找字節流的的過程.
加載器bootstrapClassLoader(啟動類加載器)最頂層的加載器,由c++實現
負責加載%JAVA_HOME%/lib目錄下的jar包和類,或者被-Xbootclasspath參數指定的路徑中的所有的類.
2. 擴展類加載器「Extension Class Loader」繼承于java.lang.ClassLoader
主要負責加載%JAVA_HOME%/lib/ext/下的jar包和類,或者被java.ext.dirs系統變量所指定的路徑下的jar包.
3. 應用類加載器「Application Class Loader」繼承于java.lang.ClassLoader
面向用戶的類加載器
負責加載當前應用classpath下的jar和類.
雙親委派模型雙親委派模型每一個類都有它對應的類加載器.
系統中的ClassLoader在協同的時候會默認啟用雙親委派模型.
在類加載的過程中,首先會判斷這個類是否被加載過.
被加載過 -> 直接返回
沒有被加載過 -> 嘗試加載
加載流程先把加載類的請求委派給該父類加載器的loadClass進行處理.
因此所有的請求最終都應該傳送到最頂層的類加載器BootstrapClassLoader中.
當父類無法處理時,才需要自己處理.
當父類加載器為null時,會使用BootstrapClassLoader作為其父類加載器
雙親委派模型的優點保證了java的穩定的運行, 可以保證類不被重復加載.
jvm區分不同的類不僅僅是根據全類名, 相同的類文件被不同的類加載器加載產生的也是兩個不同的類.
保證java核心api不被修改.
鏈接
將創建的類合成至Java虛擬機中,使之能夠被執行的過程.它可以分為驗證、準備及解析三個過程.驗證階段的目的是為了確保被加載的類滿足虛擬機的約束條件.
準備階段的目的是為了被加載類的字段分配內存.
Java代碼中對靜態字段的具體初始化則會在稍后的初始化階段進行.
構造其它跟類層次相關的數據結構.比如說用來實現虛方法的動態綁定的方法表.
解析階段的目的是,將符號引用解析成為實際引用.
如果符號引用指向一個未被加載的類、或者未被加載類的字段或方法,那么解析將觸發這個類的加載(但未必觸發這個類的鏈接以及初始化)
初始化
為標記為常量值的字段賦值,以及執行方法的過程.
java虛擬機會通過加鎖來確保類的方法僅被執行一次.
只有當初始化完成之后,類才正式成為可執行狀態.
類的初始化觸發情況當虛擬機啟動的時候,初始化用戶指定的主類.
當遇到用以新建目標類實例的new指令的時候,初始化new指令的目標類.
當遇到調用靜態方法時,初始化該類的靜態字段.
當遇到訪問靜態字段的指令時,初始化該靜態字段所在的類.
子類的初始化會觸發父類的初始化.
如果一個接口定義default方法,那么直接實現或者間接實現該接口的類的初始化,會觸發該接口的初始化.
使用反射api對某個類進行反射調用時,初始化這個類.
當初次調用MethodHandle實例時,初始化該MethodHandle指向的方法所在的類.
總結
以上是生活随笔為你收集整理的java jvm 加载_Jvm是如何加载Java类的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 英雄无敌3高清 Android,安卓TO
- 下一篇: java 开发详解_面向接口编程详解-J