面試官:今天來聊聊JVM的內存結構吧?
候選者:嗯,好的
候選者:前幾次面試的時候也提到了:class文件會被類加載器裝載至JVM中,並且JVM會負責程序「運行時」的「內存管理」
候選者:而JVM的內存結構,往往指的就是JVM定義的「運行時數據區域」
候選者:簡單來說就分為了5大塊:方法區、堆、程序計數器、虛擬機棧、本地方法棧
候選者:要值得注意的是:這是JVM「規范」的分區概念,到具體的實現落地,不同的廠商實現可能是有所區別的。

面試官:嗯,順便講下你這圖上每個區域的內容吧。
候選者:好的,那我就先從「程序計數器」開始講起吧。
候選者:Java是多線程的語言,我們知道假設線程數大於CPU數,就很有可能有「線程切換」現象,切換意味着「中斷」和「恢復」,那自然就需要有一塊區域來保存「當前線程的執行信息」
候選者:所以,程序計數器就是用於記錄各個線程執行的字節碼的地址(分支、循環、跳轉、異常、線程恢復等都依賴於計數器)
面試官:好的,理解了。
候選者:那接下來我就說下「虛擬機棧」吧
候選者:每個線程在創建的時候都會創建一個「虛擬機棧」,每次方法調用都會創建一個「棧幀」。每個「棧幀」會包含幾塊內容:局部變量表、操作數棧、動態連接和返回地址

候選者:了解了「虛擬機棧」的組成后,也不難猜出它的作用了:它保存方法了局部變量、部分變量的計算並參與了方法的調用和返回。
面試官:ok,了解了
候選者:下面就說下「本地方法棧」吧
候選者:本地方法棧跟虛擬機棧的功能類似,虛擬機棧用於管理 Java 函數的調用,而本地方法棧則用於管理本地方法的調用。這里的「本地方法」指的是「非Java方法」,一般本地方法是使用C語言實現的。
面試官:嗯...
候選者:嗯,說完了「本地方法棧」、「虛擬機棧」和「程序計數器」,哦,下面還有「方法區」和「堆」
候選者:那我先說「方法區」吧
候選者:前面提到了運行時數據區這個「分區」是JVM的「規范」,具體的落地實現,不同的虛擬機廠商可能是不一樣的
候選者:所以「方法區」也只是 JVM 中規范的一部分而已。
候選者:在HotSpot虛擬機,就會常常提到「永久代」這個詞。HotSpot虛擬機在「JDK8前」用「永久代」實現了「方法區」,而很多其他廠商的虛擬機其實是沒有「永久代」的概念的。

候選者:我們下面的內容就都用HotSpot虛擬機來說明好了。
候選者:在JDK8中,已經用「元空間」來替代了「永久代」作為「方法區」的實現了
面試官:嗯...
候選者:方法區主要是用來存放已被虛擬機加載的「類相關信息」:包括類信息、常量池
候選者:類信息又包括了類的版本、字段、方法、接口和父類等信息。
候選者:常量池又可以分「靜態常量池」和「運行時常量池」
候選者:靜態常量池主要存儲的是「字面量」以及「符號引用」等信息,靜態常量池也包括了我們說的「字符串常量池」。
候選者:「運行時常量池」存儲的是「類加載」時生成的「直接引用」等信息。

面試官:嗯...
候選者:又值得注意的是:從「邏輯分區」的角度而言「常量池」是屬於「方法區」的
候選者:但自從在「JDK7」以后,就已經把「運行時常量池」和「靜態常量池」轉移到了「堆」內存中進行存儲(對於「物理分區」來說「運行時常量池」和「靜態常量池』就屬於堆)
面試官:嗯,這信息量有點多
面試官:我想問下,你說從「JDK8」已經把「方法區」的實現從「永久代」變成「元空間」,有什么區別?
候選者:最主要的區別就是:「元空間」存儲不在虛擬機中,而是使用本地內存,JVM 不會再出現方法區的內存溢出,以往「永久代」經常因為內存不夠用導致跑出OOM異常。
候選者:按JDK8版本,總結起來其實就相當於:「類信息」是存儲在「元空間」的(也有人把「類信息」這塊叫做「類信息常量池」,主要是叫法不同,意思到位就好)
候選者:而「常量池」用JDK7開始,從「物理存儲」角度上就在「堆中」,這是沒有變化的。

面試官:嗯,我聽懂了
面試官:最后來講講「堆」這塊區域吧
候選者:嗯,「堆」是線程共享的區域,幾乎類的實例和數組分配的內存都來自於它
候選者:「堆」被划分為「新生代」和「老年代」,「新生代」又被進一步划分為 Eden 和 Survivor 區,最后 Survivor 由 From Survivor 和 To Survivor 組成
候選者:不多BB,我也畫圖吧

候選者:將「堆內存」分開了幾塊區域,主要跟「內存回收」有關(垃圾回收機制)
面試官:那垃圾回收這塊等下次吧,這個延伸下去又很多東西了
面試官:你要不先講講JVM內存結構和Java內存模型有啥區別吧?
候選者:他們倆沒有啥直接關聯,其實兩次面試過后,應該你就有感覺了
候選者:Java內存模型是跟「並發」相關的,它是為了屏蔽底層細節而提出的規范,希望在上層(Java層面上)在操作內存時在不同的平台上也有相同的效果
候選者:Java內存結構(又稱為運行時數據區域),它描述着當我們的class文件加載至虛擬機后,各個分區的「邏輯結構」是如何的,每個分區承擔着什么作用。
面試官:了解了
今日總結:JVM內存結構組成(JVM內存結構又稱為「運行時數據區域」。主要有五部分組成:虛擬機棧、本地方法棧、程序計數器、方法區和堆。其中方法區和堆是線程共享的。虛擬機棧、本地方法棧以及程序計數器是線程隔離的)

歡迎關注我的微信公眾號【Java3y】來聊聊Java面試,對線面試官系列持續更新中!
【對線面試官-移動端】系列 一周兩篇持續更新中!
【對線面試官-電腦端】系列 一周兩篇持續更新中!
原創不易!!求三連!!
