定義:Java虛擬機(jī)把描述類的數(shù)據(jù)從Class中加載到內(nèi)存琢蛤,并且校驗(yàn)、轉(zhuǎn)換解析和初始化,最終形成可以被虛擬機(jī)直接使用的java類型溅呢,這就是類的加載機(jī)制。
與那些在編譯是鏈接的語言不通康二,java的編譯鏈接過程都是在運(yùn)行期間完成的楣导,這使得java的靈活性大大提高蝌衔,java的動(dòng)態(tài)擴(kuò)展就是依賴于運(yùn)行期加載和動(dòng)態(tài)鏈接的機(jī)制來完成的闰歪。
類的加載時(shí)機(jī):類從被加載到內(nèi)存到卸載出內(nèi)存需要經(jīng)歷——加載嚎研、校驗(yàn)、準(zhǔn)備库倘、解析临扮、初始化、使用卸載等過程于樟。校驗(yàn)公条、準(zhǔn)備拇囊、解析有稱為鏈接過程迂曲。
具體過程可以參考:http://hammer.coding.me/2016/10/26/jvm-1/
加載:把java的Class文件的二進(jìn)制流加載到方法區(qū)內(nèi)存中成Class對(duì)象的過程
校驗(yàn):校驗(yàn)Class文件是不是虛擬機(jī)所識(shí)別的文件,是否符合虛擬機(jī)規(guī)范
準(zhǔn)備:將類變量賦初始值寥袭。
解析:符號(hào)引用替換為直接引用路捧。符號(hào)引用只是一個(gè)類的描述,而直接引用相當(dāng)于一個(gè)指正传黄,指向了內(nèi)存地址杰扫,所以類必須加載到內(nèi)存中。
初始化:加載類膘掰,初始化類變量調(diào)用<clinit>()構(gòu)造函數(shù)章姓。
類加載器
比較兩個(gè)類是否"相等"佳遣,只有在這兩個(gè)類是否是同一個(gè)類加載器加載出來的才有意義,如果兩個(gè)類就算來自同一個(gè)Class文件凡伊,但是類加載器不同零渐,這兩個(gè)類也是不相等的。
public static void main(String args[]) {
ClassLoader classLoader = new ClassLoader() {
@Override
public Class<?> loadClass(String name)
throws ClassNotFoundException {
String fileName = name.substring(name.lastIndexOf(".")+1) + ".class";
InputStream is = getClass().getResourceAsStream(fileName);
byte[] b = null;
try {
if(is == null) {
return super.loadClass(name);
}
b = new byte[is.available()];
is.read(b);
} catch (IOException e) {
e.printStackTrace();
}
return defineClass(name, b, 0, b.length);
}
};
Class<?> loadClass = classLoader.loadClass("com.xc.Test");
Object object = loadClass.newInstance();
System.out.println(object.getClass());
System.out.println(object instanceof com.xc.Test);
}
結(jié)果:
class com.xc.Test
false
使用流程:
1系忙、重寫ClassLoader的loadClass方法诵盼,方法參數(shù)傳入的是類的全限定名
2、根據(jù)類名獲取Class流
3银还、把字節(jié)流寫入一個(gè)字節(jié)數(shù)組
4风宁、根據(jù)Class文件的字節(jié)數(shù)組,調(diào)用defineClass方法來裝載Class對(duì)象到方法區(qū)蛹疯。
5戒财、最后調(diào)用Class.newInstance()方法實(shí)例化。
其實(shí)這就是類的裝載過程:類的裝載指的是將類的.class文件中的二進(jìn)制數(shù)據(jù)讀入到內(nèi)存中捺弦,將其放在運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)內(nèi)固翰,然后在堆區(qū)創(chuàng)建一個(gè)java.lang.Class對(duì)象,用來封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)
-
雙親委派模型
虛擬機(jī)中的類加載器分為兩大類:1羹呵、啟動(dòng)類加載器骂际,是虛擬機(jī)的一部分,有c/c++實(shí)現(xiàn)冈欢。2歉铝、有java實(shí)現(xiàn),程序員可以擴(kuò)展凑耻,其中默認(rèn)加載器為:擴(kuò)展類加載器和應(yīng)用程序加載器太示。