類加載機制詳解

常見類加載器:BootstrapClassLoader/ExtClassLoader/AppClassLoader/URLClassLoader/WebappClassLoader。html

BootstrapClassLoader(啓動類加載器):主要加載JVM自身工做須要的類,徹底由JVM本身控制;它是全部類加載器的父加載器,位於jre/lib/rt.jar。java

ExtClassLoader(擴展類加載器):它既裝載除了基本的Java API之外的擴展類,也負責裝載其餘的安全擴展功能;位於System.getProperty("java.ext.dirs")指向的目錄。bootstrap

AppClassLoader(系統類加載器):負責加載用戶在$CLASSPATH裏指定的類,位於System.getProperty("java.class.path")。安全

User-defined ClassLoader(用戶自定義類加載器):直接用代碼實現的類加載器,如:WebappClassLoader。app

 

類是如何被加載的?   它們使用雙親委派的模型來加載;基於三個機制:委託、可見性和單一性。this

委託:當一個類加載和初始化的時候,類僅在有須要加載的時候被加載。首先加載這個類的請求由AppClassLoader委託給它的父類加載器ExtClassLoader,而後再委託給BootstrapClassLoader。BootstrapClassLoader會先看看rt.jar中有沒有這個類,若是並無這個類,就把這個請求返回到ExtClassLoader,它會查看jre/lib/ext目錄下有沒有這個類,若是這個類被ExtClassLoader找到了,那麼它將被加載,而AppClassLoader不會加載這個類;而若是這個類沒有被ExtClassLoader找到,那麼再由AppClassLoader從classpath中尋找。spa

可見性:子類加載器能夠看到父類加載器加載的類,而反之則不行。.net

單一性:父加載器加載過的類不能被子加載器加載第二次。htm

 

class的加載方式?對象

隱式加載:不經過調用ClassLoader來加載須要的類,而是經過JVM自動加載所需的類到內存。如,繼承與類引用。

顯示加載:經過ClassLoader類來加載類的方式。如,this.getClass().getClassLoader().loadClass()/Class.forName()/自定義的類加載器的findClass()。

Class.forName(),ClassLoader.loadClass()的區別

http://blog.csdn.net/qq_27093465/article/details/52262340

 

自定義類加載器?

本身定義的類加載器通常繼承ClassLoader/URLClassLoader。

通常只須要重寫findClass()方法;

同一個類若是被兩個類加載器加載,那麼JVM不認爲使相同的類;

檢查被請求的類是否已經被加載到命名空間,若是已被加載,則直接返回。

若是想打破雙親委派模型,那麼就重寫整個loadClass方法

https://www.cnblogs.com/szlbm/p/5504631.html

JDK中的ClassLoader實現的:

先先查找.class是否被加載過,若是.class文件沒有被加載過,那麼會去找加載器的父加載器。

父加載器開始嘗試加載.class文件,加載成功就返回一個java.lang.Class,加載不成功就拋出一個ClassNotFoundException,給子加載器去加載。

 

雙親委派機制

一、類的加載過程採用委託模式實現

二、每一個 ClassLoader 都有一個父加載器。

三、類加載器在加載類以前會先遞歸的去嘗試使用父加載器加載。

四、虛擬機有一個內建的啓動類加載器(bootstrap ClassLoader),該加載器沒有父加載器,可是能夠做爲其餘加載器的父加載器。

雙親委派機制能很好地解決類加載的統一性問題。

JVM在斷定兩個class是否相同時,不只要判斷兩個類名是否相同,並且要判斷是否由同一個類加載器實例加載的。只有二者同時知足的狀況下,JVM才認爲這兩個class是相同的。

對一個 Class 對象來講,若是類加載器不一樣,即使是同一個字節碼文件,生成的 Class 對象也是不等的。也就是說,類加載器至關於 Class 對象的一個命名空間。

雙親委派機制則保證了基類都由相同的類加載器加載,這樣就避免了同一個字節碼文件被屢次加載生成不一樣的 Class 對象的問題。

但雙親委派機制僅僅是Java 規範所推薦的一種實現方式,它並非強制性的要求。近年來,不少熱部署的技術都已不遵循這一規則,如 OSGi 技術就採用了一種網狀的結構,而非雙親委派機制。

http://www.cnblogs.com/paddix/p/5268559.html

 

 

classloader加載一個類的過程分爲4步:

  • 第一步,從某個地方獲得咱們想要的字節碼二進制流;

  • 第二步,讀入字節碼流並轉化爲Class;

  • 第三步,連接;

  • 第四步,初始化。

ClassLoader 提供了另外一個方法 findClass 來完成第一步,

而後調用ClassLoader提供的defineClass來完成第二步,

ClassLoader提供了resolveClass方法完成第三步連接的工做

https://mp.weixin.qq.com/s/qHTXwS4BdI2gKwPzQK-D6g

    

Class.forName和ClassLoader.loadClass區別:

    第一,ClassLoader.loadClass能夠顯式指定裝載class的ClassLoader,可是Class.forName就不行了,他會默認使用調用類的ClassLoader來裝載class。

    第二,ClassLoader.loadClass僅僅加載class進來,可是不會初始化類,而Class.forName不只會加載class並且還會初始化類。

https://blog.csdn.net/liweisnake/article/details/8857744

https://blog.csdn.net/u011202334/article/details/51497998

 

 

http://blog.csdn.net/xyang81/article/details/7292380#10006-weixin-1-52626-6b3bffd01fdde4900130bc5a2751b6d1

相關文章
相關標籤/搜索