面試官:請你談談Java的類加載過程

面試官:請你談談Java的類加載過程

剛剛走出校門的應屆畢業生程序猿,如果在去尋求一份Java開發的工作時,你的面試官很有可能一邊看著你的簡歷,一邊漫不經心地問你:瞭解過Java類的加載過程嗎?

這個時候你一定要注意了,雖然這是一個老生常談的問題,但是這也是一個非常能夠考驗你Java功底的問題。

如果你答好了,這是你應該的;如果你沒答好,那麼對不起,面試官心中已經給了你不及格。

面試官:請你談談Java的類加載過程

前言

一個Java文件從編碼完成到最終執行,一般主要包括兩個過程

  • 編譯

  • 運行

編譯,即把我們寫好的java文件,通過javac命令編譯成字節碼,也就是我們常說的.class文件。

運行,則是把編譯生成的.class文件交給Java虛擬機(JVM)執行。

而我們所說的類加載過程即是指JVM虛擬機把.class文件中類信息加載進內存,並進行解析生成對應的class對象的過程。

舉個通俗點的例子來說,JVM在執行某段代碼時,遇到了class A, 然而此時內存中並沒有class A的相關信息,於是JVM就會到相應的class文件中去尋找class A的類信息,並加載進內存中,這就是我們所說的類加載過程。

由此可見,JVM不是一開始就把所有的類都加載進內存中,而是隻有第一次遇到某個需要運行的類時才會加載,且

只加載一次

類加載

類加載的過程主要分為三個部分:

  • 加載

  • 鏈接

  • 初始化

而鏈接又可以細分為三個小部分:

  • 驗證

  • 準備

  • 解析

面試官:請你談談Java的類加載過程

加載

簡單來說,加載指的是把class字節碼文件從各個來源通過類加載器裝載入內存中。

這裡有兩個重點:

  • 字節碼來源。一般的加載來源包括從本地路徑下編譯生成的.class文件,從jar包中的.class文件,從遠程網絡,以及動態代理實時編譯

  • 類加載器。一般包括啟動類加載器擴展類加載器應用類加載器,以及用戶的自定義類加載器

注:為什麼會有自定義類加載器?

  • 一方面是由於java代碼很容易被反編譯,如果需要對自己的代碼加密的話,可以對編譯後的代碼進行加密,然後再通過實現自己的自定義類加載器進行解密,最後再加載。

  • 另一方面也有可能從非標準的來源加載代碼,比如從網絡來源,那就需要自己實現一個類加載器,從指定源進行加載。

驗證

主要是為了保證加載進來的字節流符合虛擬機規範,不會造成安全錯誤。

包括對於文件格式的驗證,比如常量中是否有不被支持的常量?文件中是否有不規範的或者附加的其他信息?

對於元數據的驗證,比如該類是否繼承了被final修飾的類?類中的字段,方法是否與父類衝突?是否出現了不合理的重載?

對於字節碼的驗證,保證程序語義的合理性,比如要保證類型轉換的合理性。

對於符號引用的驗證,比如校驗符號引用中通過全限定名是否能夠找到對應的類?校驗符號引用中的訪問性(private,public等)是否可被當前類訪問?

準備

主要是為類變量(注意,不是實例變量)分配內存,並且賦予初值

特別需要注意,初值,不是代碼中具體寫的初始化的值,而是Java虛擬機根據不同變量類型的默認初始值。

比如8種基本類型的初值,默認為0;引用類型的初值則為null;常量的初值即為代碼中設置的值,final static tmp = 456, 那麼該階段tmp的初值就是456

解析

將常量池內的符號引用替換為直接引用的過程。

兩個重點:

  • 符號引用。即一個字符串,但是這個字符串給出了一些能夠唯一性識別一個方法,一個變量,一個類的相關信息。

  • 直接引用。可以理解為一個內存地址,或者一個偏移量。比如類方法,類變量的直接引用是指向方法區的指針;而實例方法,實例變量的直接引用則是從實例的頭指針開始算起到這個實例變量位置的偏移量

舉個例子來說,現在調用方法hello(),這個方法的地址是1234567,那麼hello就是符號引用,1234567就是直接引用。

在解析階段,虛擬機會把所有的類名,方法名,字段名這些符號引用替換為具體的內存地址或偏移量,也就是直接引用。

初始化

這個階段主要是對類變量初始化,是執行類構造器的過程。

換句話說,只對static修飾的變量或語句進行初始化。

如果初始化一個類的時候,其父類尚未初始化,則優先初始化其父類。

如果同時包含多個靜態變量和靜態代碼塊,則按照自上而下的順序依次執行。

總結

類加載過程只是一個類生命週期的一部分,在其前,有編譯的過程,只有對源代碼編譯之後,才能獲得能夠被虛擬機加載的字節碼文件;在其後還有具體的類使用過程,當使用完成之後,還會在方法區垃圾回收的過程中進行卸載。如果想要了解Java類整個生命週期的話,可以自行上網查閱相關資料,這裡不再多做贅述。

相關擴展知識點:

  • Java虛擬機的基本機構?

  • 什麼是類加載器?

  • 簡單談一下類加載的雙親委託機制?

  • 普通Java類的類加載過程和Tomcat的類加載過程是否一樣?區別在哪?

  • 簡單談一下Java堆的垃圾回收機制?

面試官:請你談談Java的類加載過程


分享到:


相關文章: