【歪裏諧說】1 JVM內存結構

文章內容輸出來源:拉勾教育Java高薪訓練營,做者:孫裏java

前言

對於面試中涉及的一些問題,大可能是層次多,知識點雜,不方便記憶,常常是一聽就會,一面就忘。 我想到了一個對本身頗有效的記憶方法:類比聯想記憶法。面試

其實這個方法你們很熟悉,也很經常使用,只是須要找到比較貼切且適合本身的事物進行關聯。 特此分享一下本身的經驗。本文目的不在於知識的講解,而在於知識的持久化。若有錯誤,歡迎指正。數組

不知道你們以前對jvm的內存結構能記住多少,認真看完之後嘗試每天回憶下這個場景。 由於除了第一次創建記憶鏈接之外,還須要常常在腦中反覆強化這個鏈接,才能達到深入記憶的效果。數據結構

先總體瀏覽下JVM內存結構:大致上分爲三個層次,二十多個知識點。

第一層

概念

  • 類加載器:做用是將java 文件通過編譯後會獲得 .class 文件加載到內存。jvm

  • 本地庫接口:用native修飾的,不能和abstract共同使用的,不顯示方法體但倒是用非Java語言實現方法體的方法。spa

  • 運行時數據區:java虛擬機在執行Java程序的過程當中會把它管理的內存分爲若干個不一樣的數據區域。操作系統

  • 執行引擎:jvm核心組成部分之一,創建在處理器、硬件和操做系統層面之上。引擎在執行代碼時會有解釋執行和編譯執行兩種選擇,輸入字節碼文件,解析字節碼輸出結果。線程

類比

回顧完基本概念後,咱們再關聯上一個更加容易記憶的場景,左側爲類比事物,右側爲對應知識點。對象

想象一下一輛剛剛駛入加油站的汽車:blog

  • 司機拿起加油槍(類加載器)

  • 對準加油口(本地庫接口)開始加油(開始類加載的過程,後邊會再分析)

  • 加油的目的是供給發動機可使用的燃料(執行引擎)

  • 而後纔可讓車繼續保持行駛狀態(運行時數據區)

第二層:類加載器

概念

  • 加載:指的是將類的class文件讀入到內存,併爲之建立一個java.lang.Class對象。

  • 連接:當類被加載以後,系統爲之生成一個對應的Class對象,接着將會進入連接階段,鏈接階段負責把類的二進制數據合併到JRE中。類鏈接又可分爲以下3個階段。

    • 驗證:用於檢驗被加載的類是否有正確的內部結構,並和其餘類協調一致。

    • 準備:負責爲類的靜態變量分配內存,並設置默認初始值。

    • 解析:將類的二進制數據中的符號引用替換成直接引用。

  • 初始化:爲類的靜態變量賦予正確的初始值。

  • 使用:業務處理中被引用。

  • 銷燬:再也不使用時被垃圾回收。

類比

再來類比下汽油使用的整個過程:

  • 加載:將汽油添加到油箱。

  • 連接:讓發動機的油路中充滿汽油。

    • 驗證:檢查汽油是否符合發動機要求。

    • 準備:汽油和發動機已完成啓動前的準備狀態。

    • 解析:汽油開始燃燒併產出動力,化學燃料轉換成物理的作功。

  • 初始化:發動機啓動完畢。

  • 使用:汽車行駛過程當中,發動機使用汽油持續運轉。

  • 銷燬:汽油被消耗。

第二層:運行時數據區

概念

  • 程序計數器:記錄的是正在執行的虛擬機字節碼指令的地址。

  • 虛擬機棧:Java 方法執行的內存模型。

  • 本地方法棧:區別於Java 虛擬機棧的是,Java 虛擬機棧爲虛擬機執行 Java 方法(也就是字節碼)服務,而本地方法棧則爲虛擬機使用到的Native 方法服務。

  • 堆:這塊區域是 JVM 所管理的內存中最大的一塊。線程共享,主要是存放對象實例和數組。

  • 方法區:屬於共享內存區域,存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。

類比

  • 程序計數器:記錄汽車行駛距離的里程錶。

  • 虛擬機棧:電動車電池。

  • 本地方法棧:汽油車油箱。

  • 堆:能夠堆放大件貨物的後備箱。

  • 方法區:能夠提供操做汽車的各類方法的駕駛區域。

第三層:虛擬機棧

概念

棧幀( Frame)是用來存儲數據和部分過程結果的數據結構,同時也被用來處理動態連接 (Dynamic Linking)、 方法返回值和異常分派( Dispatch Exception)。棧幀隨着方法調用而建立,隨着方法結束而銷燬——不管方法是正常完成仍是異常完成(拋出了在方法內未被捕獲的異常)都算做方法結束。

  • 局部變量表:一組變量值存儲空間,用於存放方法參數和方法內部定義的局部變量。

  • 操做數棧:一個後進先出棧,其最大深度在編譯的時候已經肯定了。當一個方法剛剛開始執行的時候,這個方法的操做數佔是空的,在方法的執行過程當中,會有各類字節碼指令往操做數佔中寫入和提取內容,這就是出棧/入棧動做。

  • 動態連接:每個棧幀都包含一個執行運行時常量池中該棧幀所屬方法的引用。持有這個引用是爲了支持方法調用過程當中的動態鏈接。

  • 返回出口:方法正常退出,將會返回程序結束其的值給上層方法,通過調整以後以指向方法調用指令後面的一條指令,繼續執行上層方法。

    • 正常完成出口:方法正確執行,執行引擎遇到方法返回的指令,回到上層的方法調用者。

    • 異常完成出口:方法執行過程當中發生異常,而且沒有處理異常,這樣是不會給上層調用者產生任何返回值。

類比

每個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。對應着每一次快遞派送:

  • 局部變量表:每次派送的貨物清單。

  • 操做數棧:貨車的貨箱,只能棧式搬運貨物。

  • 動態連接:實時動態規劃路徑。

  • 返回出口:到達終點之後就能夠返回了。

總結

最後,咱們再回顧下整個思路,方便平時反覆回憶。

  1. 貨車進入加油站進行加油時需用加油槍(類加載器)對準了加油口(本地庫接口)。加過油的車可讓發動機(執行引擎)運轉起來,並保持行駛狀態(運行時數據區)。

  2. 加油過程當中,汽油從油槍進入了油箱(加載),並抵達了發動機(連接)。這個過程當中車載電腦檢查了汽油(驗證),並使汽油和發動機都進入啓動前的準備狀態(準備)。而後汽油開始燃燒,轉化爲動力勢能(解析),發動機啓動完成後(初始化)開始使用汽油(使用),當汽油燃燒後就被消耗了(銷燬)。

  3. 因此駕駛員坐在能夠操做汽車的駕駛室(方法區)操縱貨箱(堆)載滿貨物的貨車時,會觀察記錄移動距離的里程錶和油箱指示燈(程序計數器),判斷何時須要再次加油。而油電混合的汽車也會藉助油箱(本地方法棧)的汽油燃燒給電池充電(虛擬機棧)。

  4. 貨車的目的是將貨箱(操做數棧)的貨物(局部變量)運送到目的地(返回出口),途中會藉助導航地圖實時調整路線(動態連接)。

相關文章
相關標籤/搜索