更新時間:2019-09-16 來源:黑馬程序員 瀏覽量:
什么是java類加載器?其實Java類加載器是Java運行時環(huán)境的一部分,負(fù)責(zé)動態(tài)加載Java類到Java虛擬機(jī)的內(nèi)存空間中。
Java類加載器的工作原理
一說Java代碼的執(zhí)行,接觸過Java代碼的同學(xué)肯定會想到: 編寫、編譯、運行這三個階段。編寫是在后綴名為.java的文件中, 根據(jù)Java語法規(guī)則編寫源代碼;編譯是將。java文件(源代碼文件)編譯成.class文件(字節(jié)碼文件);運行是通過JVM來執(zhí)行.class字節(jié)碼文件。
大白話解釋:
.Java文件是程序員能看懂,但是計算機(jī)看不懂的文件。需要先把它轉(zhuǎn)換成.class文件,計算機(jī)才能識別,從而來執(zhí)行。雖然這三個階段都可以通過IDE實現(xiàn),但是好多人容易忽略一個細(xì)節(jié),那就是:
在JVM執(zhí)行。class字節(jié)碼文件之前, 需要先通過”類加載器”將該字節(jié)碼文件加載到內(nèi)存中,而這個過程,就是我們要詳聊的話題。
下面我們從類加載器的概述、類加載器的分類、類加載機(jī)制三個方面來介紹java類加載器。
1、java類加載器的概述
類加載器(ClassLoader)是負(fù)責(zé)加載類的對象的,也就是將.class字節(jié)碼文件加載到JVM內(nèi)存中的。那它什么時候才會去加載.class字節(jié)碼文件呢? 答案是: 當(dāng)Java程序第一次使用某個類中的內(nèi)容,而該類的字節(jié)碼文件在內(nèi)存中不存在時,類加載器就會去加載該類的字節(jié)碼文件。
俗話說”渡人先渡己”,要想成為別人的榜樣,幫助別人。首先要做好自己。生活中如此,
類加載器也一樣。要想加載我們自定義的類,類加載器必須先完成”自加載”的過程。聊到這,不得不提的就是”類加載器的分類”了。
2、java類加載器的分類
Java中的類加載器主要分為以下四類:
(1)根類加載器(BootStrapClassLoader), 主要負(fù)責(zé)加載jre/lib/rt.jar相關(guān)的字節(jié)碼文件的。
(2)擴(kuò)展類加載器(ExtensionClassLoader), 主要負(fù)載加載 jre/lib/ext/*.jar 這些jar包的。 該類加載器在JDK1。9的時候更名為: Platform Class Loader, 其父類加載器為: null。
(3)應(yīng)用程序類加載器(ApplicationClassLoader), 主要負(fù)責(zé)加載用戶自定義的類以及classpath環(huán)境變量所配置的jar包的。 該類加載器在JDK1.9的時候更名為: System ClassLoader, 其父類加載器為: ExtensionClassLoader。
(4)自定義類加載器(UserClassLoader), 負(fù)責(zé)加載程序員指定的特殊目錄下的字節(jié)碼文件的。大多數(shù)情況下,自定義類加載器只需要繼承ClassLoader這個抽象類,重寫findClass()和loadClass()兩個方法即可。
如下圖:
到這,相信大家對類加載器已經(jīng)初步有一定的認(rèn)識和理解了。接下來,我們寫代碼來驗證一下,代碼和打印結(jié)果如下:
到這里,代碼就已經(jīng)驗證完畢了。其實我們現(xiàn)在一直在研究的是JVM類加載機(jī)制的"加載循序", 現(xiàn)在,我們來研究下它的"檢查順序",請你思考,假設(shè):
D:\compile、ext\*.jar、rt.jar三類中都有A.class,那么A.class是否會被加載3次,如果不會,它的加載順序是什么樣的?
答案是: 不會被加載3次,并最終會由BootStrapClassLoader來加載A.class。
原因是因為,APPClassLoader類加載器(以下簡稱: app)加載之前,會先詢問ExtClassLoader類加載器(以下簡稱: ext)是否加載。如果ext加載,app就不加載了,反之則app加載。同樣, ext在加載之前, 也會詢問BootStrapClassLoader類加載器(以下簡稱: bootstrap)是否加載, 如果bootstrap加載,則ext就不加載了,反之,則ext加載。這也是: JVM類加載機(jī)制的”雙親委派機(jī)制”。
2、java類加載器的類加載機(jī)制
最后,我們再來聊一聊”類加載機(jī)制”,在JVM中類加載機(jī)制主要有3種:
(1)全盤加載。顧名思義,就是當(dāng)某一個類加載器加載某個.class文件時, 默認(rèn)也會連同該文件所依賴的.class一起加載(除非顯示聲明通過某個指定的類加載器加載)。
(2) 緩存機(jī)制。即所有類加載器已經(jīng)加載過的.class文件都會被保存到緩存中,下次使用該.class文件時,JVM會優(yōu)先從緩存中查找,如果沒有,才會去加載指定的字節(jié)碼文件,這也是為什么當(dāng)字節(jié)碼文件變化后, 需要重啟JVM后才能看到修改效果的原因。
(3)雙親委派。大白話解釋,兒子(App)要星星,他自己實現(xiàn)不了,就找他老爹(Ext)要,他老爹能實現(xiàn)的話就給他了,實現(xiàn)不了,就找他爺爺(BootStrap)要,說: 你孫子要天上的星星。他爺爺如果能實現(xiàn)就給了,如果也實現(xiàn)不了,就會告訴他爹(Ext),讓你兒子(App)自己實現(xiàn)吧。這種情況有點極端,屬于誰都沒有加載,則程序報錯,會拋出異常。
(4)總結(jié): 類加載器自上而下檢查(App --> Ext --> BootStrap),自下而上加載(BootStrap -->
Ext --> App)。
推薦了解:大數(shù)據(jù)培訓(xùn)課程