jvm:类加载器与双亲委派模型
兩個類相等需要類本身相等,并且使用同一個類加載器進行加載。這是因為每一個類加載器都擁有一個獨立的類名稱空間。
這里的相等,包括類的 Class 對象的 equals() 方法、isAssignableFrom() 方法、isInstance() 方法的返回結果為 true,也包括使用 instanceof 關鍵字做對象所屬關系判定結果為 true。
類加載器分類
從 Java 虛擬機的角度來講,只存在以下兩種不同的類加載器:
-
啟動類加載器(Bootstrap ClassLoader),這個類加載器用 C++ 實現,是虛擬機自身的一部分;
-
所有其他類的加載器,這些類由 Java 實現,獨立于虛擬機外部,并且全都繼承自抽象類 java.lang.ClassLoader。
從 Java 開發人員的角度看,類加載器可以劃分得更細致一些:
-
啟動類加載器(Bootstrap ClassLoader)此類加載器負責將存放在 <JRE_HOME>\lib 目錄中的,或者被 -Xbootclasspath 參數所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別,如 rt.jar,名字不符合的類庫即使放在 lib 目錄中也不會被加載)類庫加載到虛擬機內存中。啟動類加載器無法被 Java 程序直接引用,用戶在編寫自定義類加載器時,如果需要把加載請求委派給啟動類加載器,直接使用 null 代替即可。
-
擴展類加載器(Extension ClassLoader)這個類加載器是由 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)實現的。它負責將 <JAVA_HOME>/lib/ext 或者被 java.ext.dir 系統變量所指定路徑中的所有類庫加載到內存中,開發者可以直接使用擴展類加載器。
-
應用程序類加載器(Application ClassLoader)這個類加載器是由 AppClassLoader(sun.misc.Launcher$AppClassLoader)實現的。由于這個類加載器是 ClassLoader 中的 getSystemClassLoader() 方法的返回值,因此一般稱為系統類加載器。它負責加載用戶類路徑(ClassPath)上所指定的類庫,開發者可以直接使用這個類加載器,如果應用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器。
雙親委派模型
應用程序都是由三種類加載器相互配合進行加載的,如果有必要,還可以加入自己定義的類加載器。
下圖展示的類加載器之間的層次關系,稱為類加載器的雙親委派模型(Parents Delegation Model)。該模型要求除了頂層的啟動類加載器外,其余的類加載器都應有自己的父類加載器。這里類加載器之間的父子關系一般通過組合(Composition)關系來實現,而不是通過繼承(Inheritance)的關系實現。
?
1. 工作過程
一個類加載器首先將類加載請求傳送到父類加載器,只有當父類加載器無法完成類加載請求時才嘗試加載。
2. 好處
使得 Java 類隨著它的類加載器一起具有一種帶有優先級的層次關系,從而使得基礎類得到統一。
優先級:通過啟動類加載器加載的類 > 擴展類加載器加載的類 > 應用程序加載器加載的類
例如 java.lang.Object 存放在 rt.jar 中,如果編寫另外一個 java.lang.Object 的類并放到 ClassPath 中,程序可以編譯通過。由于雙親委派模型的存在,所以在 rt.jar 中的 Object 比在 ClassPath 中的 Object 優先級更高,這是因為 rt.jar 中的 Object 使用的是啟動類加載器,而 ClassPath 中的 Object 使用的是應用程序類加載器。rt.jar 中的 Object 優先級更高,因此在各種類加載器環境中都是同一個類。
每一個類,都需要由加載它的類加載器和類本身來確定其在JVM中的唯一性?
總結
以上是生活随笔為你收集整理的jvm:类加载器与双亲委派模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM:内存分配与回收策略?Full G
- 下一篇: JVM:内存划分总结