類經(jīng)過javac編譯后,生成.class文件保存下來,然后經(jīng)過類加載器加載類至內(nèi)存,生成java.lang.Class類的實(shí)例,這個(gè)實(shí)例就是程序訪問這個(gè)類的入口,通過這個(gè)class實(shí)例的newInstance方法即可得到這個(gè)類的實(shí)例對(duì)象。
JVM中的類的加載器主要有三種:啟動(dòng)類加載器,拓展類加載器,應(yīng)用類加載器。
啟動(dòng)類加載器(Bootstrap classLoader):又稱為引導(dǎo)類加載器,由C++編寫,無法通過程序得到。主要負(fù)責(zé)加載JAVA中的一些核心類庫,主要是位于<JAVA_HOME>/lib/rt.jar中。
拓展類加載器(Extension classLoader):主要加載JAVA中的一些拓展類,位于<JAVA_HOME>/lib/ext中,是啟動(dòng)類加載器的子類。
應(yīng)用類加載器(System classLoader): 又稱為系統(tǒng)類加載器,主要用于加載CLASSPATH路徑下我們自己寫的類,是拓展類 加載器的子類。
比如我們自己寫了一個(gè)類Student類,經(jīng)過編譯后會(huì)得到Student.class文件,然后經(jīng)過類加載器得到Class實(shí)例,例如通過
Class.forName("com.***.Student"),通過全路徑加載進(jìn)來。然后我們用Student.class.getClassLoader()得到它的類加載器,得到的是AppClassLoader(即系統(tǒng)類加載器),如果用Student.class.getClassLoader().getParent()得到的是它的父加載器ExtClassLoader(即拓展類加載器),然后用Student.class.getClassLoader().getParent().getParent()得到將會(huì)是Null,因?yàn)閱?dòng)類加載器是用C++寫的,我們無法通過程序直接得到.
Object類是<BootStrap ClassLoader>加載器加載的;
我們自己寫的類是< System ClassLoader>類加載器加載的
<BootStrap ClassLoader>不是類加載器子類
類加載器的三大特性:委托性、可見性、單一性
委托性:每個(gè)類中都有一個(gè)自己的類加載器的屬性,這也就是為什么可以通過Student.class.getClassLoader()來 獲取自己的類加載器。當(dāng)一個(gè)類加載器要加載一個(gè)類時(shí),它會(huì)先委托自己的父類加載器來加載,只有當(dāng)父加載器無法加載類時(shí),才會(huì)自己去加載。例如我們寫了一個(gè)類Student,它的類加載器是System ClassLoader,它首先會(huì)委托給它的父加載器即Extension ClassLoader,然后Extension ClassLoader又會(huì)委托給它的父加載器BootStrap ClassLoader,啟動(dòng)類加載器無法加載這個(gè)類,交給拓展類加載器,拓展類加載器也無法加載,然后才輪到系統(tǒng)類加載器進(jìn)行加載。
可見性:可見性指的是父加載器無法利用子加載器加載的類,而子加載器可以利用父加載器加載的類。
單一性:一個(gè)類只會(huì)被一個(gè)類加載器加載一次,不會(huì)被重復(fù)加載。
我們自己也可以寫自己的類加載器以滿足自己特定的要求,只要實(shí)現(xiàn)ClassLoader這個(gè)類即可,但是要滿足上面所說的類加載器的三種特性。