【JVM】ClassLoader

類加載器

從我的上一篇JVM體系結構文章的中可以看出,在 JVM 的內存模型中,類加載器是處於一個較爲重要的位置。

類加載器負責將 Java 的 .class 文件加載入 JVM 的內存區域,.class 文件的開頭都有特定的文件標識,並且將這些內容轉換成方法區中的運行時數據結構,類加載器只負責加載 .class 文件,Execution Engine 決定其是否能運行。

下圖是類加載器將 .class 文件加載到 JVM 的過程:

類加載器將 .class 文件加載後,會初始化一個類模板,該類的所有實例都會通過這個類模板創建出來。

類加載器種類

類加載器當然不止一種,從大體上,類加載器可以分爲4種。

Java 虛擬機中自帶的類加載器有:

  1. 啓動類加載器(Bootstrap):通過C++實現的
  2. 擴展類加載器(Extension):通過Java實現的
  3. 應用程序加載器(AppClassLoader):也稱爲系統類加載器

用戶自定義的類加載器:

  1. Java.lang.ClassLoader 的子類,用戶可以自定義類的加載方式

下圖爲各個類加載器的層級關係圖:

我們用代碼來測試一下,通過 Java 原生 Object 類和自定義的 App 類,查看他們的類加載器和類加載器的層級關係。

可以看出,啓動類加載器在打印的時候是 null,這是因爲啓動類加載器是通過 C++ 語言實現的,Java 沒辦法直接操作。自定義的 App 類就是應用程序加載器。

雙親委派模型

在類加載器中還需要提及的就是類加載器的雙親委派模型

當一個類需要加載的時候,首先他不會自己去加載這個類,而是把這個類加載的請求委派給父類的類加載器加載,每一層類加載器都是這樣,直到委派給啓動類加載器,只有最頂層的類加載器無法加載這個類請求時,子類的類加載器纔會開始嘗試加載。

優點

使用雙親委派模型可以防止污染 Java 源代碼,比如我們自定義了一個 string 類,但是 java 源代碼中已經有了 string,由於我們自己自定義的 string 類加載器屬於應用程序加載器,根據雙親委派模型,會先讓啓動類加載器加載,所以會加載 jdk 中的 string 類,保證了使用不同的類加載器最終得到的是同一個對象。


我們做一個小小的測試,新建一個類叫做String,與JDK包中的String同名,實例化這個String類,看看會發生什麼??

這裏我在String類的空構造上打印了一句話,想看看在創建String對象的時候會不會調用到。

打印出來的結果是報錯,也就證明了Java檢測到我們自定義的String類和JDK中的String類同名,啓動類加載器加載時拋出錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章