類的裝載就是通過類加載器把.class二進(jìn)制文件轉(zhuǎn)入jvm的方法區(qū),并在堆區(qū)創(chuàng)建描述該類的java.lang.Class對象,用來封裝數(shù)據(jù)。如果要獲取這個Class對象可以通過實例的getClass()或者直接通過的類的靜態(tài)方法.class。JVM規(guī)范允許預(yù)先加載,在預(yù)料到某個類要使用的時候就加載這個類,如果這個類不存在,也不會馬上拋出異常,只有在程序主動使用這個類的時候才會拋出異常,如果這個類一直沒有使用,那么就永遠(yuǎn)不會拋出異常。
對于驗證是驗證加載的二進(jìn)制文件是否符合規(guī)范,如有沒有繼承final類等。
準(zhǔn)備就是為靜態(tài)成員分配內(nèi)存空間,并設(shè)置默認(rèn)值,byte short long flloat 都是0,對象類型為null,boolean類型為false.
解析就是對于編譯型常量使用直接的內(nèi)存地址代替變量,如final static int a =10;但是對于在編譯的時候不能得到具體值得變量不做變換,如final static int a =Math.random()。在完成上述工作后,就是對于靜態(tài)變量的初始化。
對于靜態(tài)變量的初始化時在主動使用的時候才會初始化他們。以下6種情況是主動使用
創(chuàng)建類的實例,途經(jīng)包括:使用new 創(chuàng)建對象實例,clone等
使用反射方法
使用靜態(tài)方法
使用類或者接口的靜態(tài)變量,給靜態(tài)變量賦值
創(chuàng)建子類
把類聲明為啟動類,如: java Test01
這時候會初始化類的靜態(tài)變量,執(zhí)行靜態(tài)代碼塊
我想主要說一下類的卸載:只有沒有任何引用指向Class對象的時候,這時候才會卸載類,結(jié)束類的生命周期。在JVM中有三類加載器根加載器,擴(kuò)展加載器,系統(tǒng)加載器,JVM始終保持這幾類加載器的引用,加載器會把其加載的類放在一個集合中,這樣就保留著對于Class對象的引用(不可以操作JVM的加載器),所以由JVM的加載器加載的類是不會卸載的,如果要驗證一個類是否可以卸載,可以自己創(chuàng)建一個類加載器(繼承ClassLoader)Loader,加在一個類Test,然后讓loader的實例賦值為null,loader加載的Class對象也賦值為null;再次創(chuàng)建Loader的實例,并加載Test,這時候可以打印這兩個Test的Class對象的哈希值(是不一樣的),如一下代碼(加載器MyclassLoader.java不給出了):
如果注釋掉第9句,那么會拋出類重復(fù)加載異常。