來源:期待華麗轉身
cnblogs.com/developerxiaofeng/p/9214969.html

Java崗位面試,JVM是對程式員基本功考察,通常會問你對JVM了解嗎?
可以分幾部分回答這個問題,首先JVM記憶體劃分 | JVM垃圾回收的含義 | 有哪些GC演算法 以及年輕代和老年代各自特點等等,
1) JVM記憶體劃分:
① 方法區 (執行緒共享) 常量 靜態變數 JIT(即時編譯器)編譯后代碼也在方法區存放
② 堆記憶體(執行緒共享) 垃圾回收的主要場地
③ 程式計數器 當前執行緒執行的位元組碼的位置指示器
④ Java虛擬機堆疊(堆疊記憶體) :保存區域變數,基本資料型別以及堆記憶體中物件的參考變數
⑤ 本地方法堆疊 (C堆疊):為JVM提供使用native方法的服務
通過這幅圖了解一下

JDK 1.8同JDK 1.7 最大的區別是:元資料取代了永久代.元空間的本質和永久代類似,都是對JVM規范中的方法區的實作.其元空間和永久代之間的最大區別在于:元資料空間不在虛擬機中,而是在本地記憶體中
詳細了解一下各個部分
01)程式計數器(PC暫存器)
程式計數器的定義: 程式計數器是一塊較小的記憶體空間,是當前執行緒正在執行的哪一條位元組碼指令的地址,若當前執行緒正在執行的是一個本地方法,那么此時程式計數器為Undefined
程式計數器的作用:
-
位元組碼解釋器通過改變程式計數器來依次獲取指令,從而實作代碼的流程的控制
-
在在多執行緒情況下,程式計數器記錄的是當前執行緒執行的執行的位置,從而當執行緒切換回來時,就知道上次執行緒執行到哪了
程式計數器的特點
-
是一塊較小的記憶體空間
-
執行緒私有,每個執行緒都有自己的程式計數器
-
生命周期:隨著執行緒的創建而創建,隨著執行緒的銷毀而銷毀
-
是一個唯一不會出現的OutOfMemoryError的記憶體區域
02)Java虛擬機堆疊
定義: 描述Java方法運行程序的記憶體模型
Java虛擬機堆疊會為每一個即將運行的Java方法創建一塊叫做"堆疊幀"的區域,用于存放該方法運行程序中的一些資訊,如 區域變數表 /運算元堆疊 /動態鏈接 /方法出口資訊 .............

壓堆疊出堆疊程序:
當方法運行程序中需要創建區域變數時,就將區域變數的值存入堆疊幀的區域變數表中
Java虛擬機堆疊的堆疊頂是當前正在執行的活動堆疊,也就是當前正在執行的方法,PC暫存器也會指向這個地址,只有這個活動的堆疊幀的本地變數可以被運算元堆疊操作,當前這個堆疊幀中呼叫另一個方法,與之對應的額堆疊幀又會被創建,新創建的堆疊幀壓入堆疊頂,變成當前的活動堆疊幀,方法結束后,當前堆疊幀的回傳值變成新的活動堆疊幀的中的運算元堆疊的一個運算元,如果沒有回傳值,那么新的活動堆疊幀中運算元堆疊的運算元沒有變化
由于Java虛擬機堆疊是執行緒對應的,資料不是共享的,因此不用關心資料一致性問題,也不會存在同步鎖的問題
特點
-
區域變數表隨著堆疊幀的創建而創建,他的大小在編譯時確定,創建時只需分配事先規定的大小即可,在方法運行的程序中,區域變化表的大小不會發生變化
-
Java虛擬機堆疊會出現兩種例外:StackOverFlowError和OutOfMemoryError
-
StackOverFlowError若Java虛擬機堆疊的大小不允許動態擴展,那么當前執行緒請求的堆疊的深度超過當前的Java虛擬機堆疊的最大深度是,就會拋出此例外
-
OutOFMemoryError,若允許動態擴展,那么當前執行緒的請求的堆疊記憶體用完了,無法再動態擴展時,拋出此例外
-
Java虛擬機堆疊也是執行緒私有,隨著執行緒創建而創建,隨著執行緒的結束而銷毀
03)本地方法堆疊(C堆疊)
定義: 是為了JVM運行native方法準備的空間,由于很多native方法都是用C語言實作的,所以通常又叫C堆疊,它與Java虛擬機堆疊實作的功能類似,只不過本地方法堆疊描述本地方法運行程序的記憶體模型
堆疊幀變化程序:
本地方法被執行時,在本地方法堆疊也會創建一塊堆疊幀,用于存放該方法的區域變數表 /運算元堆疊 /動態鏈接 /方法出口等資訊; 方法結束后,相應的堆疊幀也會出堆疊,并釋放記憶體空間.也會拋出StackOverFlowError和OutOfMemoryError例外
04) 堆
定義: 堆是用來物件的記憶體空間,幾乎所有的物件都存盤在堆中
特點:
-
執行緒共享,整個Java虛擬機只有一個堆,所有執行緒都訪問同一個堆.
-
在虛擬機啟動時創建
-
是垃圾回收的主要場地
-
進一步可分為:新生代(Eden區 From Survior To Surviror) 老年代
-
不同的區域存放的不同生命周期的物件,這樣可以根據不同區域使用不同的垃圾回收演算法,更具有針對性. 堆的大小也可以固定也可以擴展,對于主流的虛擬機,堆大小可擴展的,因此當執行緒請求分配的記憶體,但堆已滿,且記憶體已無法再擴展,就拋出OutOfMemoryError例外
05)方法區
定義: Java虛擬機規范中定義方法區是堆的一個邏輯部分,方法區存放以下資訊 已被虛擬機加載的類資訊 /常量 /靜態變數 /即時編譯后代碼
特點:
-
執行緒共享.方法區是堆的一個邏輯部分,因此和堆一樣,都是執行緒共享,整個虛擬機中只有一個方法區
-
永久代 方法區中的資訊一般需要長期存在,而且它又是堆的邏輯磁區,因此用堆的劃分方法,把方法區稱為"永久代"
-
記憶體回收的效率低.方法區中的資訊一般需要長期存在,回收一遍只有少量資訊無效.主要回收的目標是: 對常量池的回收;對型別的卸載
-
Java虛擬機規范l對方法區的要求比較寬松,和堆一樣,允許固定大小.也允許動態擴展,還允許不實作垃圾回收
運行時常量池:
方法區中存放:類資訊 常量 靜態變數 即時編譯器變編譯后代碼.常量就存放在運行時常量池中.當類被Java虛擬機加載后,.class檔案中的常量就存在方法區的運行常量池,而且在運行期間,可以向常量池中添加新的常量,如String類的intern()方法就能在運行期間向常量池中添加字串常量
06) 直接記憶體(堆外記憶體)
直接記憶體是除Java虛擬機之外的記憶體,但有可能被Java使用
操作直接記憶體:
在NIO中引入了一種基于通道和快取的IO方式,他可以呼叫本地方法的直接分配Java虛擬機之外的記憶體,然后通過一個存盤在堆中的DirectByteBuffer物件直接操作該記憶體,而無需將外部記憶體中資料復制到堆中再進行操作,從而提高資料操作的效率,直接記憶體的大小不受Java虛擬機,也會拋出OutOfMemoryError例外
直接記憶體和堆記憶體比較:
-
直接記憶體申請空間耗費更高的性能
-
直接記憶體讀取IO的性能優于普通的堆記憶體
-
直接記憶體的作用鏈:本地IO-->直接記憶體-->本地IO
-
堆記憶體的作用鏈:本地IO-->直接記憶體-->非直接記憶體-->直接記憶體--->本地IO
-
服務器管理員在配置虛擬機引數時,會根據實際記憶體設定 -Xmx等引數資訊,但經常忽略直接記憶體,使得各個記憶體區域總和大于物理記憶體,從而導致動態擴展時出現OutOFMemoryError
2)類似 -Xms -Xmn這些引數的含義
堆記憶體分配
① : JVM初始分配的記憶體由-Xms指定,默認是物理記憶體的1/64
②: JVM最大分配的記憶體由-Xmx指定,默認是物理記憶體的1/4
③: 默認空余堆記憶體小于40%時,JVM就會增加堆直到-Xmx的最大限制;空余堆記憶體大于70%時,JVM會減少堆直到-Xms的最小限制
④: 因此服務器一般設定-Xms -Xmx相等以避免在每次GC后調整堆大小. 物件的堆記憶體由成為垃圾回收器的自動記憶體管理系統回收
非堆記憶體分配:
①:JVM使用-XX:PermSize 設定非堆記憶體的初始值,默認物理記憶體的1/64;
② :由XX:MaxPermSize設定設定最大非堆記憶體的大小
③: -Xmn2G :設定年輕代的大小為2G
④ :-XX:SurvivorRatio ,設定年輕代中Eden區與Survivor區的比值
3)垃圾回收的演算法有哪些?
① 參考計數法:原理是在此物件有個參考,即增加一個計數,洗掉一個參考則減少一個計數.垃圾回收時,只收集計數為0的物件.此演算法的最致命的無法處理回圈參考的問題
②: 標記-清除 :此演算法分兩個階段,第一階段從參考的根節點開始標記所有被參考的物件,第二階段遍歷整個堆,把未標記的物件清除,此演算法需要暫停應用,同時產生記憶體碎片
③: 復制演算法 此演算法把記憶體劃分為兩個相等的區域,每次只使用一個區域,垃圾回收時,遍歷當前使用的區域,把正在使用的物件復制到另一個區域中每次演算法每次只處理正在使用的物件,因此復制的成本比較小,同時復制過去以后還能進行相應的記憶體整理,不會出現"碎片問題",此演算法的缺點也很明顯,需要兩倍的記憶體空間
④: 標記-整理:此演算法結合了"標記-清除"和:復制演算法的兩個的優點,也是分兩個階段,第一個階段從根節點開始標記所有被參考物件,第二階段遍歷整個堆,清除未標記的物件并且把存活的物件"壓縮"到堆的其中一塊,按順序排放,,此演算法避免"標記-清除"的碎片問題,同時也避免"復制"的空間問題
4)root搜索演算法中,哪些可以作為root?
-
被啟動類(bootstrap加載器)加載的類和創建的物件
-
JavaStack中參考的物件(堆疊記憶體中參考的物件)
-
方法區中靜態參考
關注公眾號Java技術堆疊回復"面試"獲取我整理的2020最全面試題及答案,
推薦去我的博客閱讀更多:
1.Java JVM、集合、多執行緒、新特性系列教程
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
4.Java、后端、架構、阿里巴巴等大廠最新面試題
覺得不錯,別忘了點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/141646.html
標籤:Java
上一篇:Java中多執行緒的使用(超級超級詳細)執行緒安全+執行緒鎖原理決議+保證執行緒安全的三種方式 (同步代碼塊+同步方法+lock鎖) 5
下一篇:linux下安裝redis
