每日一面——談談你對JVM的運行時數據區的理解

菜雞每日一面系列打卡24

每天一道面試題目 

助力小夥伴輕鬆拿offer

堅持就是勝利,我們一起努力!

題目描述

談談你對JVM的運行時數據區的理解。

題目分析

從今日起,菜雞的每日一面系列進軍Java虛擬機(以下簡稱JVM)了。Java之所以是跨平臺的語言,可以說JVM是最大的功臣,沒有之一。JVM屏蔽了底層的細節,從而使Java達到了“一次編譯,到處運行”的目的。

上面這段話如果說得通俗一點就是,我們編寫的Java程序都是運行在JVM上的。接下來,就讓我們從超高頻面試題——JVM運行時數據區開始,逐步瞭解JVM這個熟悉又陌生的老朋友吧!

題目解答

01

JVM簡介

首先需要明確的是,JVM其實是一個概念,而不是一個實物。用Java語言做一個形象的比喻,它更像是Java中的類,而不是對象實例。後續關於JVM的非概念層面的所有描述,如果不特殊指明,都是基於HotSpot(JVM的一種主流實現)來說的。

虛擬機是相對於物理機來說的一個概念,虛擬機不是看得見摸得着的機器,其本質其實就是一段程序,並沒有想象的那麼神祕,如果感興趣,你甚至可以翻閱HotSpot的源碼,你會發現,它主要是由C++實現的,這可能是基於效率的考量,也可能是歷史原因,在此不作深究。這段話的主要目的就是說明,虛擬機其實就是一段相對來說比較複雜的代碼而已,不要懼怕它。

既然JVM本質上就是一段程序,那麼它最終還是要落到實際的物理機上運行,它可以管理物理機的一部分內存,並在執行Java程序時,將其劃分爲若干個不同的數據區域,這也就是我們今天要講到的JVM運行時數據區

02

JVM運行時數據區

經典的JVM運行時數據區主要分爲五部分:程序計數器,虛擬機棧,本地方法棧,堆,方法區。這些區域有各自的用途,以及創建和銷燬的時間,有的區域隨着虛擬機進程的啓動而一直存在,有些區域則是依賴用戶線程的啓動和結束而建立和銷燬。

我們通過周志明老師的《深入理解Java虛擬機》第3版中的一張圖,來仔細學習一下各個區域之間的關係。

這張圖堪稱經典,它簡潔明瞭地闡釋了JVM運行時數據區不同區域之間的關係,雖然隨着時間的推移,HotSpot的更新會和這張圖上表明的關係略有出入,但不能說這張圖過時了,它是一種內存管理的設計思想,應該把這張圖深深印在腦海中好好消化。

接下來,我們對這五個內存區域逐一進行概況。

  • 程序計數器:當前線程所執行的字節碼的行號指示器它是程序控制流的指示器,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。它是線程私有的,同時,它也是唯一一個在《Java虛擬機規範》中沒有規定任何OutOfMemoryError情況的區域

  • 虛擬機棧:Java方法執行的線程內存模型。它是線程私有的,每個方法被執行的時候,JVM都會同步創建一個棧幀用於存儲局部變量表、操作數棧、動態連接、方法出口等信息。每一個方法被調用直至執行完畢的過程,就對應着一個棧幀在虛擬機棧中從入棧到出棧的過程。在棧深度溢出或者棧擴展失敗時分別拋出StackOverFlowErrorOutOfMemoryError異常。

  • 本地方法棧:與虛擬機棧類似,區別在於本地方法棧是爲Native方法而非Java方法服務。在棧深度溢出或者棧擴展失敗時分別拋出StackOverFlowErrorOutOfMemoryError異常。

  • 堆:用於存放對象實例。Java世界裏“幾乎”所有的對象實例都在這裏分配內存。它是線程共享的,也是垃圾回收的主要場所。有關垃圾回收的具體知識將在後續文章中進行講解。如果在Java堆中沒有內存完成實例分配,並且堆也無法再擴展時,將會拋出OutOfMemoryError異常。

  • 方法區:用於存儲已被虛擬機加載的類型信息、常量、靜態變量、即時編譯器編譯後的代碼緩存等數據。它是線程共享的。如果方法區無法滿足新的內存分配需求時,將拋出OutOfMemoryError異常。

參考資料

《深入理解Java虛擬機》第3版 周志明

以上便是菜雞對JVM運行時數據區的一些總結,供大家參考。

學習 | 工作 | 分享

????長按關注“有理想的菜雞

只有你想不到,沒有你學不到

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