JVM之类的加载过程(三):初始化——>Initialization
本篇主要講解類的初始化,也就是上圖紅框的部分。
類的初始化都做了哪些事呢?
一、初始化:
1.初始化階段就是執行類構造器方法<clinit>() 的過程。
2.此方法不需要定義,是javac編譯器自動收集類中的所有類變量的賦值動作和靜態代碼塊中的語句合并而來。
發現只要有類變量的賦值和靜態代碼塊,系統默認生成<clinit>() 方法。
看如下代碼:
它的字節碼文件:
就會發現沒有<clinit>()方法。
3.構造器方法中指令按語句在源文件中出現的順序進行執行。
4.<clinit>() 不同于類的構造器,一旦一個類進行聲明后,系統默認會生成該類的無參構造器,也就對應的是字節碼文件中的<init>() 方法。
5.若該類具有父類,JVM 會保證子類的<clinit>() 執行前,父類的<clinit>() 已經執行完畢。
如上圖,執行ClinitTest1的main() 方法,首先會進行ClinitTest1 加載到內存中,然后進行鏈接,初始化完成后,調用它的main() 方法執行打印輸出Son.B,又
由于Son 繼承Father類,會先執行Father類的<Clinit>() 方法,將A=1,在執行靜態代碼塊,A=2,再去執行Son的<clinit>() 方法,將A=2的值賦值給B,最后輸出
B的值為2.
6. 虛擬機必須保證一個類的<clinit>() 方法在多線程下被同步加鎖,也就是一個類只會被加載一次。存放到方法區中,并進行緩存。
二、初始化時機:(也就是何時才會進行初始化):
?
三、虛擬機自帶的加載器:
1、啟動類加載器(引導類加載器,Bootstrap ClassLoader):
a.這個類加載使用c/c++ 語言實現的,嵌套在JVM 內部。
b.它是來加載Java的核心庫(JAVA_HOME/jre/lib/rt.jar、resources.jar 或sun.boot.class.path 路徑下的內容),用于提供JVM自身需要的類
如下圖代碼:
運行結果:
c.并不繼承java.lang.ClassLoader,沒有父類加載器。
d.加載擴展類和應用程序類加載器,并指定為他們的父類加載器。
e.出去安全考慮,Bootstrap 啟動類加載器只加載包名為java、javax、sun 等開頭的類。
2、擴展類加載器:
a、Java語言編寫,由sun.misc.Launcher$ExtClassLoader實現。
b、派生于ClassLoader
c、父類加載器為啟動類加載器。
d、從java.ext.dirs 系統屬性所指定的目錄中加載類庫,或從JDK的安裝目錄的jre/lib/ext子目錄下加載類庫,如果用戶創建的jar放在此目錄下,也會自動由擴展類加載器加載。
如下圖代碼:
運行結果:
3、應用程序類加載器(系統類加載器,AppClassLoader)
a、java語言編寫,由sun.misc.Launcher$AppClassLoader實現
b、派生于ClassLoader類
c、父類加載器為擴展類加載器。
d、它負責加載環境變量classpath 或系統屬性 java.class.path 指定路徑下的類庫。
e、該類加載時程序 默認的類加載器,一般來說,java 應用的類都是由他來加載完成的
f、通過ClassLoader#getSystemClassLoader() 方法可以獲取到該類加載器
?
總結
以上是生活随笔為你收集整理的JVM之类的加载过程(三):初始化——>Initialization的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 21g2
- 下一篇: scrapy 项目实战(一)----爬