面试官问我JVM内存结构,我真的是
面試官:今天來聊聊JVM的內(nèi)存結(jié)構(gòu)吧?
候選者:嗯,好的
候選者:前幾次面試的時候也提到了:class文件會被類加載器裝載至JVM中,并且JVM會負責(zé)程序「運行時」的「內(nèi)存管理」
候選者:而JVM的內(nèi)存結(jié)構(gòu),往往指的就是JVM定義的「運行時數(shù)據(jù)區(qū)域」
候選者:簡單來說就分為了5大塊:方法區(qū)、堆、程序計數(shù)器、虛擬機棧、本地方法棧
候選者:要值得注意的是:這是JVM「規(guī)范」的分區(qū)概念,到具體的實現(xiàn)落地,不同的廠商實現(xiàn)可能是有所區(qū)別的。
面試官:嗯,順便講下你這圖上每個區(qū)域的內(nèi)容吧。
候選者:好的,那我就先從「程序計數(shù)器」開始講起吧。
候選者:Java是多線程的語言,我們知道假設(shè)線程數(shù)大于CPU數(shù),就很有可能有「線程切換」現(xiàn)象,切換意味著「中斷」和「恢復(fù)」,那自然就需要有一塊區(qū)域來保存「當(dāng)前線程的執(zhí)行信息」
候選者:所以,程序計數(shù)器就是用于記錄各個線程執(zhí)行的字節(jié)碼的地址(分支、循環(huán)、跳轉(zhuǎn)、異常、線程恢復(fù)等都依賴于計數(shù)器)
面試官:好的,理解了。
候選者:那接下來我就說下「虛擬機棧」吧
候選者:每個線程在創(chuàng)建的時候都會創(chuàng)建一個「虛擬機棧」,每次方法調(diào)用都會創(chuàng)建一個「棧幀」。每個「棧幀」會包含幾塊內(nèi)容:局部變量表、操作數(shù)棧、動態(tài)連接和返回地址
候選者:了解了「虛擬機棧」的組成后,也不難猜出它的作用了:它保存方法了局部變量、部分變量的計算并參與了方法的調(diào)用和返回。
面試官:ok,了解了
候選者:下面就說下「本地方法棧」吧
候選者:本地方法棧跟虛擬機棧的功能類似,虛擬機棧用于管理 Java 函數(shù)的調(diào)用,而本地方法棧則用于管理本地方法的調(diào)用。這里的「本地方法」指的是「非Java方法」,一般本地方法是使用C語言實現(xiàn)的。
面試官:嗯...
候選者:嗯,說完了「本地方法棧」、「虛擬機棧」和「程序計數(shù)器」,哦,下面還有「方法區(qū)」和「堆」
候選者:那我先說「方法區(qū)」吧
候選者:前面提到了運行時數(shù)據(jù)區(qū)這個「分區(qū)」是JVM的「規(guī)范」,具體的落地實現(xiàn),不同的虛擬機廠商可能是不一樣的
候選者:所以「方法區(qū)」也只是 JVM 中規(guī)范的一部分而已。
候選者:在HotSpot虛擬機,就會常常提到「永久代」這個詞。HotSpot虛擬機在「JDK8前」用「永久代」實現(xiàn)了「方法區(qū)」,而很多其他廠商的虛擬機其實是沒有「永久代」的概念的。
候選者:我們下面的內(nèi)容就都用HotSpot虛擬機來說明好了。
候選者:在JDK8中,已經(jīng)用「元空間」來替代了「永久代」作為「方法區(qū)」的實現(xiàn)了
面試官:嗯...
候選者:方法區(qū)主要是用來存放已被虛擬機加載的「類相關(guān)信息」:包括類信息、常量池
候選者:類信息又包括了類的版本、字段、方法、接口和父類等信息。
候選者:常量池又可以分「靜態(tài)常量池」和「運行時常量池」
候選者:靜態(tài)常量池主要存儲的是「字面量」以及「符號引用」等信息,靜態(tài)常量池也包括了我們說的「字符串常量池」。
候選者:「運行時常量池」存儲的是「類加載」時生成的「直接引用」等信息。
面試官:嗯...
候選者:又值得注意的是:從「邏輯分區(qū)」的角度而言「常量池」是屬于「方法區(qū)」的
候選者:但自從在「JDK7」以后,就已經(jīng)把「運行時常量池」和「靜態(tài)常量池」轉(zhuǎn)移到了「堆」內(nèi)存中進行存儲(對于「物理分區(qū)」來說「運行時常量池」和「靜態(tài)常量池』就屬于堆)
面試官:嗯,這信息量有點多
面試官:我想問下,你說從「JDK8」已經(jīng)把「方法區(qū)」的實現(xiàn)從「永久代」變成「元空間」,有什么區(qū)別?
候選者:最主要的區(qū)別就是:「元空間」存儲不在虛擬機中,而是使用本地內(nèi)存,JVM 不會再出現(xiàn)方法區(qū)的內(nèi)存溢出,以往「永久代」經(jīng)常因為內(nèi)存不夠用導(dǎo)致跑出OOM異常。
候選者:按JDK8版本,總結(jié)起來其實就相當(dāng)于:「類信息」是存儲在「元空間」的(也有人把「類信息」這塊叫做「類信息常量池」,主要是叫法不同,意思到位就好)
候選者:而「常量池」用JDK7開始,從「物理存儲」角度上就在「堆中」,這是沒有變化的。
面試官:嗯,我聽懂了
面試官:最后來講講「堆」這塊區(qū)域吧
候選者:嗯,「堆」是線程共享的區(qū)域,幾乎類的實例和數(shù)組分配的內(nèi)存都來自于它
候選者:「堆」被劃分為「新生代」和「老年代」,「新生代」又被進一步劃分為 Eden 和 Survivor 區(qū),最后 Survivor 由 From Survivor 和 To Survivor 組成
候選者:不多BB,我也畫圖吧
候選者:將「堆內(nèi)存」分開了幾塊區(qū)域,主要跟「內(nèi)存回收」有關(guān)(垃圾回收機制)
面試官:那垃圾回收這塊等下次吧,這個延伸下去又很多東西了
面試官:你要不先講講JVM內(nèi)存結(jié)構(gòu)和Java內(nèi)存模型有啥區(qū)別吧?
候選者:他們倆沒有啥直接關(guān)聯(lián),其實兩次面試過后,應(yīng)該你就有感覺了
候選者:Java內(nèi)存模型是跟「并發(fā)」相關(guān)的,它是為了屏蔽底層細節(jié)而提出的規(guī)范,希望在上層(Java層面上)在操作內(nèi)存時在不同的平臺上也有相同的效果
候選者:Java內(nèi)存結(jié)構(gòu)(又稱為運行時數(shù)據(jù)區(qū)域),它描述著當(dāng)我們的class文件加載至虛擬機后,各個分區(qū)的「邏輯結(jié)構(gòu)」是如何的,每個分區(qū)承擔(dān)著什么作用。
面試官:了解了
今日總結(jié):JVM內(nèi)存結(jié)構(gòu)組成(JVM內(nèi)存結(jié)構(gòu)又稱為「運行時數(shù)據(jù)區(qū)域」。主要有五部分組成:虛擬機棧、本地方法棧、程序計數(shù)器、方法區(qū)和堆。其中方法區(qū)和堆是線程共享的。虛擬機棧、本地方法棧以及程序計數(shù)器是線程隔離的)
總結(jié)
以上是生活随笔為你收集整理的面试官问我JVM内存结构,我真的是的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入了解Mybatis架构设计
- 下一篇: 面试官问:什么是布隆过滤器?