java类加载器_类加载器
回顧一下類加載過程
類加載過程:加載->連接->初始化。連接過程又可分為三步:驗(yàn)證->準(zhǔn)備->解析。
一個(gè)非數(shù)組類的加載階段(加載階段獲取類的二進(jìn)制字節(jié)流的動(dòng)作)是可控性最強(qiáng)的階段,這一步我們可以去完成還可以自定義類加載器去控制字節(jié)流的獲取方式(重寫一個(gè)類加載器的 loadClass() 方法)。數(shù)組類型不通過類加載器創(chuàng)建,它由 Java 虛擬機(jī)直接創(chuàng)建。
所有的類都由類加載器加載,加載的作用就是將 .class文件加載到內(nèi)存。
類加載器總結(jié)
JVM 中內(nèi)置了三個(gè)重要的 ClassLoader,除了 BootstrapClassLoader 其他類加載器均由 Java 實(shí)現(xiàn)且全部繼承自java.lang.ClassLoader:
雙親委派模型
雙親委派模型介紹
每一個(gè)類都有一個(gè)對(duì)應(yīng)它的類加載器。系統(tǒng)中的 ClassLoder 在協(xié)同工作的時(shí)候會(huì)默認(rèn)使用 雙親委派模型 。即在類加載的時(shí)候,系統(tǒng)會(huì)首先判斷當(dāng)前類是否被加載過。已經(jīng)被加載的類會(huì)直接返回,否則才會(huì)嘗試加載。加載的時(shí)候,首先會(huì)把該請(qǐng)求委派該父類加載器的 loadClass() 處理,因此所有的請(qǐng)求最終都應(yīng)該傳送到頂層的啟動(dòng)類加載器 BootstrapClassLoader 中。當(dāng)父類加載器無法處理時(shí),才由自己來處理。當(dāng)父類加載器為null時(shí),會(huì)使用啟動(dòng)類加載器 BootstrapClassLoader 作為父類加載器。
每個(gè)類加載都有一個(gè)父類加載器,我們通過下面的程序來驗(yàn)證。
public class ClassLoaderDemo {public static void main(String[] args) {System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader());System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent());System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent());} }Output
ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2 The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586 The GrandParent of ClassLodarDemo's ClassLoader is nullAppClassLoader的父類加載器為ExtClassLoader ExtClassLoader的父類加載器為null,null并不代表ExtClassLoader沒有父類加載器,而是 BootstrapClassLoader 。
其實(shí)這個(gè)雙親翻譯的容易讓別人誤解,我們一般理解的雙親都是父母,這里的雙親更多地表達(dá)的是“父母這一輩”的人而已,并不是說真的有一個(gè) Mother ClassLoader 和一個(gè) Father ClassLoader 。另外,類加載器之間的“父子”關(guān)系也不是通過繼承來體現(xiàn)的,是由“優(yōu)先級(jí)”來決定。官方API文檔對(duì)這部分的描述如下:
The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a “parent” class loader. When loading a class, a class loader first “delegates” the search for the class to its parent class loader before attempting to find the class itself.雙親委派模型實(shí)現(xiàn)源碼分析
雙親委派模型的實(shí)現(xiàn)代碼非常簡(jiǎn)單,邏輯非常清晰,都集中在 java.lang.ClassLoader 的 loadClass() 中,相關(guān)代碼如下所示。
private final ClassLoader parent; protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 首先,檢查請(qǐng)求的類是否已經(jīng)被加載過Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {//父加載器不為空,調(diào)用父加載器loadClass()方法處理c = parent.loadClass(name, false);} else {//父加載器為空,使用啟動(dòng)類加載器 BootstrapClassLoader 加載c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {//拋出異常說明父類加載器無法完成加載請(qǐng)求}if (c == null) {long t1 = System.nanoTime();//自己嘗試加載c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}雙親委派模型的好處
雙親委派模型保證了Java程序的穩(wěn)定運(yùn)行,可以避免類的重復(fù)加載(JVM 區(qū)分不同類的方式不僅僅根據(jù)類名,相同的類文件被不同的類加載器加載產(chǎn)生的是兩個(gè)不同的類),也保證了 Java 的核心 API 不被篡改。如果沒有使用雙親委派模型,而是每個(gè)類加載器加載自己的話就會(huì)出現(xiàn)一些問題,比如我們編寫一個(gè)稱為 java.lang.Object 類的話,那么程序運(yùn)行的時(shí)候,系統(tǒng)就會(huì)出現(xiàn)多個(gè)不同的 Object 類。
如果我們不想用雙親委派模型怎么辦?
為了避免雙親委托機(jī)制,我們可以自己定義一個(gè)類加載器,然后重寫 loadClass() 即可。
完善修正(issue871:類加載器一問的補(bǔ)充說明):
自定義加載器的話,需要繼承 ClassLoader 。如果我們不想打破雙親委派模型,就重寫 ClassLoader 類中的 findClass() 方法即可,無法被父類加載器加載的類最終會(huì)通過這個(gè)方法被加載。但是,如果想打破雙親委派模型則需要重寫 loadClass() 方法
自定義類加載器
除了 BootstrapClassLoader 其他類加載器均由 Java 實(shí)現(xiàn)且全部繼承自java.lang.ClassLoader。如果我們要自定義自己的類加載器,很明顯需要繼承 ClassLoader。
推薦閱讀
- 深入分析Java ClassLoader原理
- 《2020最新Java基礎(chǔ)精講視頻教程和學(xué)習(xí)路線!》
- 老大難的 Java ClassLoader 再不理解就老了
- Java類加載器(ClassLoader)
鏈接:類加載器
來源:github
總結(jié)
以上是生活随笔為你收集整理的java类加载器_类加载器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: music算法_“要热爱 请深爱”系列(
- 下一篇: nofollow标签_如何Nofollo