java類加載機制,再也不怕面試官的刁難

上一篇我們詳細的講解了java 虛擬機的內存模型(要想精通java,你必須得知道java的內存模型,不忽悠),並且知道了我們寫的代碼分別是怎麼存在JVM的哪個內存區域中。今天我們來看另一個重要的問題,類加載機制的核心知識,這個知識也是面試經常問到的。

我們的java代碼是怎麼運行起來的?

我們在寫好java代碼之後,都是先進行打包,打成jar包或者war包,最後丟到服務器上啓動JVM進程就能運行了。大概是下面這樣的一個過程。

那麼,現在我們就來看看這些類是怎麼被加載到JVM中,它的加載機制又是什麼樣的

 

java類什麼時候會被加載

我們寫的java類,從被加載到使用,一般會經歷下面幾個步驟:

加載-->驗證-->準備-->解析-->初始化-->使用-->卸載

我們首先就要知道,我們的類是什麼時候被加載進JVM的?其實,我們有一定經驗後就已經知道了,類在被使用的時候就會被加載進JVM中。

public class MyTest {

public static void main(String[] args) {

Study study = new Study();

study.studyJava();

}

}

//

public class Study {

public void studyJava() {

System.out.println("This is Java");

}

}

我們來看上面代碼,當我們啓動JVM運行到有main()方法的時候,這個時候MyTest.class這個類就會被加載進來,然後運行到有一個new Study() 的時候,發現需要實例化一個Study對象,就會去class文件找到study類加載進來,如下圖

 

 

類連接過程

類的連接主要是指類驗證、準備以及初始化的過程。這些我們暫時只用先了解下功能就行,一般在我們開發中不怎麼會用到。

  1. 驗證階段:是指我們加載進來的class文件是否合法,有沒有被篡改等
  2. 準備階段:就是將我們加載來的類分配相應的內存空間,以及給變量指定初始值等,例如,private int type; 這種的
  3. 解析階段:這個主要是將符號引用替換爲直接引用的過程。

最爲核心的階段就是初始化,所以,我們來單獨說一下初始化。

老規矩,我們先來看一段代碼:

public class Study {

public static int strategyType = Configuration.getInt("config.strage.type");

}

上面我們說過在類的準備階段,是分配內存空間以及給出初始化值的,然而我們現在的這個Configuration.getInt("config.strage.type") 在準備階段會不會執行這段代碼呢?其實是不會執行的,這裏只會分配內存和給個初始值“0”,Configuration.getInt("config.strage.type") 是在初始化階段進行執行的,然後再將結果賦值給strategyType的,還有就是我們經常寫的static{}代碼塊也是在初始化階段進行執行的。

什麼時候會初始化一個類

現在我們已經弄明白了什麼是初始化操作了,接下來我們來看看初始化的相關規則:

在new一個對象的時候,這個時候就會觸發類的加載到初始化的全過程。

包含main()方法的類,需要立馬初始化。

如果在初始化一個類時,發現他的父類沒有進行初始化,那麼就得先初始化父類。

 

 

類加載器以及雙親委派機制

通過上面的學習,我們已經很清楚了類的加載到初始化的整個過程,那麼下面我們就需要去了解類加載器了,只有具備類加載器,上面那些過程才能得以實現。在我們java中主要有如下四種類加載器:

1,Bootstrap ClassLoader 啓動類加載器

這個主要是用來加載我們安裝在機器上JDK目錄的核心類,即在我們java 目錄的lib包裏的各種jar包,我們啓動JVM的時候,第一步就是加載這lib裏面的類。

2,Extension ClassLoader 擴展類加載器

這個也是加載我們jdk默認的擴展類,在我們java目錄的lib\ext目錄裏面的各種jar包。

3,Application 應用程序類加載器

這個類加載器就是加載我們在classPath 環境變量指定的路徑的類,也就是我們自己開發出來的各種類。

4,自定義類加載器

自定義就是根據自己的需要,設計一種自己的加載器去加載我們寫的程序,和上面3種是互斥的。

雙親委派機制

上面我們將我們java裏面的四大類加載器進行了梳理,並且知道了每個加載器各是加載什麼內容的,那麼最後我們還需要知道這些類加載器是怎麼配合運行我們的系統的。

其實,JVM的類加載器是有親子層級關係的,自上到下分別是啓動類加載器、擴展類加載器、應用程序類加載器乃至最後一層是自定義類加載器。這就是一個雙親委派的機制。

 

怎麼進行委派

就是指如果咱們的應用程序類加載器需要加載一個類的時候,它第一步就是先找它的父類加載器去加載,直到最頂層的類加載器。如果父類加載器在自己負責的範圍內並未找到這個類的話,就會把加載的權利讓給自己的子類去加載

我們還是來用一個例子來說明下吧,比如我們要加載Study這個類的時候:

  1. 應用程序類加載器會去找他的父親擴展類加載器去幫它加載這個Study這個類。
  2. 擴展類加載器這個時候也會去請求他自己的父親啓動類加載器去幫忙加載Study這個類。
  3. 啓動類加載器找了一圈發現這個Study並不在他的加載範圍內,然後,就說不在我這兒,你自己去找。
  4. 擴展類就自己找,也找了一圈,仍然是沒找到,就會下發他的兒子,你自己的類,你自己找去
  5. 應用程序類加載器這個時候就會自己找Study這個類,然後給加載進JVM中

下面我們來通過一張圖來整體認識下類的加載過程以及雙親委派機制

總結,今天我們將我們常用的JVM類加載機制以及他的雙親委派模型進行了詳細的講解,大家只要認真學習了,相信,在我的工作開發中會更加的清晰明朗,同時,對於面試官的刁難也會有一套自己的應對方案。

在公衆號菜單“成神之路” 獲取當前最牛架構,java python、機器學習等各大視頻以及面試資料

 

關於架構師修煉

本號旨在分享一線互聯網各種技術架構解決方案,分佈式以及高併發等相關專題,同時會將作者的學習總結進行整理並分享。

在公衆號“架構師修煉”菜單可獲得專屬java架構視頻資料,更多java、python、人工智能、小程序、大前端等可看菜單,無私奉獻
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章