總結了一些jvm面試題
更多更詳細的面試資料點贊+關注,私信我獲取
JVM載入流程和執行時資料區如下圖所示:
執行時資料區
方法區
方法區
用於儲存已經被載入的類資訊、常量、靜態變數、編譯後的程式碼以及 執行時常量池
等。
堆
堆
主要存放一些資料,比如物件例項、陣列等。
堆記憶體會劃分為年輕代和老年代,年輕代又會分為Eden和Servivor區,Survivor也會分為FromPlace和ToPlace。
虛擬機器棧
虛擬機器棧
描述的是JVAV方法執行的記憶體模型。每個方法被執行的時候同時都會建立一個棧幀
,用於儲存區域性變量表
,運算元棧
,動態連結
,方法出口
等資訊,不存在垃圾回收問題,只要執行緒結束,該棧就釋放。
本地方法棧
和棧作用類似,但是本地方法棧執行的是native方法。
程式計數器
程式計數器
可以看做是當前執行緒所執行的行號指示器。
記憶體洩露和記憶體溢位
記憶體洩露的原因
- 物件是可達的(一直被引用)
- 物件不會被使用。
這些物件不會被GC所回收,但是卻一直佔用記憶體。
記憶體溢位的原因
- 記憶體洩露導致堆疊記憶體不斷增大
- 大量的jar,class檔案載入,裝載類的空間不夠
- 操作大量的物件導致堆記憶體空間用滿
GC的方式
- Minor GC: 年輕代,頻率高,速度快
- Major GC:老年代
- Full GC:整個堆(年輕代,老年代)
虛擬機器堆的年輕代和年老代
- 當Eden空間滿了之後,會觸發一次Minor GC,GC之後還存活
- 如果物件的大小大於Eden的二分之一會直接分配在老年代區。如果老年代也分配不下,會做一次老年代的major GC。
- 如果minor GC後,survivor仍然放不下,則放到老年代。
- 動態年齡判斷。大於等於某個年齡段的物件超過了Servivor空間的一半,則直接進入老年代。
雙親委派模式
當一個類收到載入請求時,它不會先自己去嘗試載入,而是委派給父類去完成。
作用:為了解決類載入過程中的安全性問題。
- 假設有一個開發者自己編寫了一個名為
java.lang.Object
的類,想借此欺騙JVM。現在他要使用自定義ClassLoader
來載入自己編寫的java.lang.Object
類。 - 然而幸運的是,雙親委託模型不會讓他成功。因為JVM會優先在
BootstrapClassLoader
的路徑下找到java.lang.Object
類,並載入它。
類的例項化順序
- 父類靜態成員和靜態初始化塊,按程式碼塊中出現的順序依次執行。
- 子類靜態成員和靜態初始化塊,按程式碼塊中出現的順序依次執行。
- 父類例項成員和例項初始化塊,按程式碼塊中出現的順序依次執行。
- 父類構造方法
- 子類例項成員和例項初始化塊,按程式碼塊出現的順序依次執行。
- 子類構造方法。
JVM中一次完整的GC流程是怎樣的?
YGC和FGC表示什麼?
- YGC(Young GC): 對新生代堆進行GC。頻率比較高,因為大部分物件的存活壽命較短,在新生代裡被回收,效能耗費較小。
- FGC(Full GC): 全堆範圍的GC。預設堆空間使用到達80%的時候回觸發FGC、
JVM垃圾回收演算法有哪些?
我們常用的垃圾回收器一般採用分代收集演算法。
標記-清除演算法
演算法分為標記和清除兩個階段,首先標記出所有需要回收的物件,在標記完成後統一回收所有標記的物件。
標記壓縮演算法
首先先標記需要回收的物件,然後讓所有存活的物件都向一端移動,最終清理掉端邊界以外的記憶體。
複製演算法
將可用記憶體劃分為大小相等的兩塊,每次用掉其中的一塊。當著一塊的記憶體用完了,就將還存活的物件複製到另外一塊上面,然後再把已使用的記憶體空間一次清理掉。
分代收集演算法
將JAVA堆分為新生代和老年代,這樣就可以根據各個年代的特點採用最適合的收集演算法。
常見的垃圾收集器有哪些?
CMS收集器
CMS收集器
,CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器。- CMS收集器需要消耗額外的CPU和記憶體資源,在CPU和記憶體資源緊張時,會加重系統負擔,
- CMS無法處理浮動垃圾,CMS的
標記-清除
演算法,會導致大量的空間碎片的產生。
G1收集器
G1(Garbage-First)是一款面向服務端的垃圾收集器,主要針對配備多顆處理器及大容量記憶體的機器,具備極高概率滿足GC停頓的同時,還具備高吞吐量效能特徵。
Serial收集器
Serial
收集器,是最古老,最穩定以及效率高的序列收集器。- 只使用一個執行緒去回收,可能產生較長的停頓。