深入理解Java類加載器
https://blog.csdn.net/zhoudaxia/article/details/35824249
https://blog.csdn.net/zhoudaxia/article/details/35897057
- BootstrapClassLoader:只能用于加載JDK核心類庫,系統(tǒng)變量為sun.boot.class.path下面的類。該目錄下的%JAVA_HOME%/jre/lib/下的resources.jar;rt.jar等核心類庫,該loader底層采用C++編寫,自然你也就不能調(diào)用啦。
- ExtClassLoader :用于加載一些擴(kuò)展類,系統(tǒng)變量為java.ext.dirs中的類。作用:加載開發(fā)者自己擴(kuò)展類。
- AppClassLoader:用于加載用戶類,這個(gè)就是java.class.path下的類,也就是我們自己編寫出來的類。
其中這三個(gè)加載器順序?yàn)锽ootstrapClassLoader>ExtClassLoader>AppClassLoader,為啥要這樣設(shè)計(jì)?主要是為了擴(kuò)展與安全。首先你將BootstrapClassLoader作為一個(gè)核心類加載器,只加載核心類,不與其他耦合在一起。并且為何要設(shè)計(jì)這三個(gè)加載器,就應(yīng)該和雙親委派機(jī)制放在一起了。
何為雙親委派機(jī)制:簡單來說就是當(dāng)你需要加載類的時(shí)候,必須從頂級(jí)父加載器先加載,如果父加載不了,則交給子加載器。就相當(dāng)于小孩子要做決定的時(shí)候,要先問問父親怎么做。
為什么要有這種雙親委派機(jī)制:
保證唯一性:試想,如果沒有雙親委派模型而是由各個(gè)類加載器自行加載的話,如果用戶編寫了一個(gè)java.lang.Object的同名類并放在ClassPath中,多個(gè)類加載器都去加載這個(gè)類到內(nèi)存中,系統(tǒng)中將會(huì)出現(xiàn)多個(gè)不同的Object類,那么類之間的比較結(jié)果及類的唯一性將無法保證.
保證安全:由于所有的用戶類都會(huì)先通過bootstrapclassloader 查看里面有沒有該類資源,有則直接安徽或者加載,從而保證了底層的類一定是預(yù)先加載的,這樣可以對虛擬機(jī)的安全得到了很好的保證。
關(guān)于自定義類加載模型
思考以下情景:
- 首先,是為了區(qū)分同名的類:假定存在一個(gè)應(yīng)用服務(wù)器,上面部署著許多獨(dú)立的應(yīng)用,同時(shí)他們擁有許多同名卻不同版本的類庫。試想,這時(shí)候 jvm 該怎么加載這些類同時(shí)能盡可能的避免掉類加載時(shí)對同名類的差異檢測呢?當(dāng)然是不同的應(yīng)用都擁有自己獨(dú)立的類加載器了。
- 其次,是為了更方便的加強(qiáng)類的能力:類加載器可以在 load class 時(shí)對 class 進(jìn)行重寫和覆蓋,在此期間就可以對類進(jìn)行功能性的增強(qiáng)。比如添加面向切面編程時(shí)用到的動(dòng)態(tài)代理,以及 debug 等原理。怎么樣達(dá)到僅修改一個(gè)類庫而不對其他類庫產(chǎn)生影響的效果呢?一個(gè)比較方便的模式就是每個(gè)類庫都可以使用獨(dú)立的類加載器
小結(jié):
jvm 需要有不同的類加載器,因?yàn)樗?strong>一方面允許你在一個(gè) jvm 里運(yùn)行不同的應(yīng)用程序,另一方面方便你獨(dú)立的對不同類庫進(jìn)行運(yùn)行時(shí)增強(qiáng)。