类加载器、双亲委派模型
目錄
1.簡介
2.類和類加載器
3.雙親委派模型
3.1 啟動類加載器:
3.2 擴展類加載器
3.3應用程序類加載器
3.4? 類加載器的雙親委派模型(Parents Delegation Model)
雙親委派模型的工作過程:
好處:
實現:
4.破壞雙親委派模型
1.簡介
虛擬機設計團隊把類加載階段的“通過一個類的全限定名來獲取描述此類的二進制字節流”這個動作。實現這個動作的代碼模塊稱為“類加載器”。
?
它是在JVM外部實現的,以便讓應用程序自己決定如何獲取所需要的類。
2.類和類加載器
對于任何一個類,都需要由加載它的類加載器和這個類本身一同確立其在JVM中的唯一性。
每一個類加載器,都有一個獨立的類名稱空間。即,比較兩個類是否“相等”,只有在這兩個類是由同一個類加載器加載的前提下才有意義,否則,即使兩個類來源于同一個Class文件,被同一個虛擬機加載,只要加載它們的類加載器不同,那么這兩個類就必定不相等。
- “相等”:包括代表類對象的equals()方法、isAssignableFromo()方法、isInstance()方法的返回結果,也包括使用instanceof關鍵字做對象所屬關系判定等情況。
- 如果沒有注意到類加載器的影響,在某些情況下,可能會產生具有迷惑性的結果,如下代碼:
輸出:
上述代碼構造了一個簡單的類加載器。
- 可加載與自己同一路徑下的Class文件。
- 使用這個類加載器加載了一個名為“CSDNpattern.Test”的類,并實例化了這個類的對象。
- 輸出結果中,第一句表明這個類確實是“CSDNpattern.Test”;但第二句發現這個類和“CSDNpattern.Test”做所屬類型檢查的時候卻返回了false。
- 因為虛擬機中存在了兩個Test類,一個室友系統應用程序類加載器加載的,一個是由自定義的類加載器加載的。
- 雖然都是來自同一個Class文件,但是是兩個獨立的類,做對象所屬類型檢查時結果自然為false。
3.雙親委派模型
從JVM角度來看,只存在兩種不同的類加載器:
- 啟動類加載器(BootStrap ClasLoader):使用C++實現,是虛擬機自身的一部分;
- 所有其他的類加載器:由Java實現,獨立于虛擬機外部,并且全都繼承自抽象類java.lang.Object。
從Java開發人員角度,還可以分的更細,絕大部分Java程序都會用到一下3種系統提供的類加載器:
3.1 啟動類加載器:
- 負責將存放在<JAVA_HOME>\lib目錄里的,或者被-Xbootclasspath參數指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別,如rt.jar,名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內存中。
- 它無法被Java程序直接引用。
- 用戶在編寫自定義類加載器時,如果需要把加載請求為派給引導類加載器,納智捷使用null代替即可。如下代碼所示(提示錯):
3.2 擴展類加載器
Extension ClassLoader
負責加載<JAVA_HOME>\lib\ext目錄中的,或者被java.ext.dirs系統變量所指定的路徑中的所有類庫,開發者可以使用擴展類加載器。
3.3應用程序類加載器
Application ClassLoader
它是ClassLoader中的getSystemClassLoader()放的返回值,所有一般也稱為系統類加載器。
它負責加載用戶類路徑(ClassPath)上所指定的類庫,開發者可以直接使用這個類加載器。
如果應用程序中沒有自定義過自己的類加載器,一般情況系下這個就是程序中的默認的類加載器。
?
我們的應用陳香菇都是由這3種類加載器相互配合進行加載的。
如有必要,還可以加入自定義的類加載器。
3.4? 類加載器的雙親委派模型(Parents Delegation Model)
這些類加載器的關系一般如下圖所示:
圖示的這種類加載器之間的這種層次關系,稱為類加載器的雙親委派模型(Parents Delegation Model)
雙親委派模型中要求除了頂層的啟動類加載器外,其余的類加載器都應當有自己的父類加載器。
這里的類加載器之間的父子關系一般不會以繼承(inheritance)的關系來實現,而是使用組合(Composition)關系來復用父加載器的代碼。
類加載器的雙親委派模型在JDK1.2期間被引入并被廣泛應用于之后幾乎所有的Java程序中。
但它并不是一個強制性的約束模型,而是Java設計者推薦給開發者的一種類加載器實現方式。
3.4.1 雙親委派模型的工作過程
3.4.2 好處
Java類隨著它的類加載器一起舉杯了一種帶有優先級的層次關系。
例如,類java.lang.Object,它存放在rt.jar中,無論哪一個類加載器都要加載這個類,最終都是為派給處于模型最頂端的啟動類加載器進行加載。因此Object類在程序的各個類加載器環境中都是同一個類。
相反,如果沒有使用這個模型,由各個類加載器自行去加載的話,如果用戶自己編寫了一個稱為java.lang.Object的類,并放在程序ClassPath中,那系統將會出現多個不同的Object類。Java類型體系中最基礎的行為也就無法保證,應用程序也變得一片混亂。
3.4.3 實現
實現這個模型的代碼都集中在在java.lang.ClassLoader的loadClass()中。如下代碼所示:
{//首先檢查請求的類是否已經被加載過了Class c=findLoadedClass(name);if(c==null) {try {if(parent!=null)c=parent.loadClass(name,false);elsec=findBootStrapClassOrNull(name);}catch(ClassNotFoundException e) {//如果父類加載器 拋出ClassNotFoundException//說明父類加載器無法完成加載請求}if(c==null) {//在父類加載器無法完成加載的時候//再調用本身的findClass方法來進行類加載c=findClass(name);}}if(resolve) {resolveClass(c);} }邏輯:
4.破壞雙親委派模型
雙親委派模型主要出現過3次較大規模的“被破壞”情況;
整理自《深入理解Java虛擬機——JVM高級特性與最佳實踐》
總結
以上是生活随笔為你收集整理的类加载器、双亲委派模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM运行时结构、Java内存管理、JV
- 下一篇: Java内存泄露和内存溢出、JVM命令行