1. 程式人生 > >JVM面試十問

JVM面試十問

1. JVM執行時劃分哪幾個區域?哪些區域是執行緒共享的?哪些區域是執行緒獨佔的?

JVM執行時一共劃分:程式計數器、虛擬機器棧、堆、本地方法棧、方法區。

執行緒共享的資料區域:堆、方法區。

執行緒獨享的資料區域區域:程式計數器、虛擬機器棧、本地方法棧。

2. 這幾個記憶體區域分別存放什麼資料?

程式計數器記錄當前執行緒執行的位置;

虛擬機器棧儲存基本資料型別以及物件的引用等;

堆儲存物件例項;

本地方法棧與虛擬機器棧類似,它為Native方法服務;

方法區儲存被JVM載入的類資訊、常量、靜態變數等。

3. GC回收演算法

(1)標記-清除演算法:首先標記出需要回收的物件,標記完成後統一清除。此演算法缺點是標記-清楚效率不高,且容易出現大量不連續的碎片空間。

(2)複製演算法:將記憶體空間劃分成兩部分,每次只使用一個記憶體空間部分,當一個記憶體空間使用完,將會把存活的物件複製到另一空間,然後一次性清理掉該部分空間。此演算法缺點是記憶體利用率較低,只有一半。

(3)標記-整理演算法:和標記-清楚演算法相同也是先標記出需要回收的物件,但在標記完成後不是直接清除而是將存活的物件像一側進行移動,再清除邊界之外的記憶體。

4. 這三種GC回收演算法在JVM中是如何應用的?

GC主要發生在JVM的堆記憶體中,堆記憶體分為"新生代"和"老年代",新生代的GC稱為"Minor GC",老年代的GC稱為"Major GC"。

新生代中的GC演算法使用複製演算法:新生代中分為了Eden區和Survivor區(Survivor from和Survivor to),新產生的物件例項先在Eden區,Eden區滿了過後再在Survivor from區,如果Survivor from區也滿了後,將進行Minor GC(複製演算法),將存活的物件複製到Survivor to區,此時清除Eden區和Survivor from區,此時Survivor from成為新的Survivor to。新的物件又將在Eden區域進行分配,周而復始。

老年代中的GC演算法使用標記-清除演算法/標記-整理演算法,視具體的GC回收器而定。

5. 頻繁的Full GC會帶來什麼問題?

CPU佔用率過高,系統出現卡頓。

6. 什麼是OOM記憶體溢位,它發生在哪塊記憶體區域

OOM通常發生在堆記憶體上,指的是記憶體物件沒有及時回收,造成沒有多餘的記憶體分配給新的物件,此時應該定位程式中是否在頻繁建立物件而沒有及時回收,或者設定JVM的引數-Xms、-Xmx。

但OOM還有一種情況發生在虛擬機器棧,此時虛擬機器棧並不是因為遞迴太深造成StackOverflow,而是的的確確發生了OOM。首先,虛擬機器棧作為執行緒獨享的記憶體區域,總的虛擬機器棧記憶體大小有限,也就是可分配的執行緒大小有限,當每個虛擬機器棧設定的記憶體大小過大時,此時可分配的執行緒大小就變少,繼續建立過多的執行緒可能會導致無法再分配記憶體空間,造成虛擬機器棧的OOM。此時的解決辦法時,適當設定虛擬機器棧的記憶體大小-Xss,以便能建立更多的執行緒。

7.常用的GC回收器有哪些,有什麼特點?

CMS:通常對老年代的物件進行GC,基於標記-清除演算法,是一個低停頓、併發收集的GC回收器。它的GC過程一共分為4個步驟:

①初始標記,標記GC Roots能關聯的物件(即存活的物件),會停止使用者執行緒。

②併發標記,不會停止使用者執行緒,和使用者執行緒一起工作標記可達物件。

③重新標記,標記因為在“併發標記”階段新產生的物件。

④併發清除,同用戶執行緒一起工作,清理需要清理的物件。

缺點:

①佔用CPU資源

②無法處理併發標記期間產生的浮動垃圾

③由於採用標記-清楚演算法,會產生大量的記憶體碎片

G1:應用於整個堆上的記憶體,物理上不再劃分年輕代與老年代,只做邏輯保留,採用標記-整理演算法,是一個可對停頓時間預測的低停頓、併發收集的GC回收器。它的GC過程同CMS類似,一共分為4個步驟:

①初始標記,同CMS回收器一致,標記出存活的物件。

②併發標記,同CMS回收器一致,和使用者執行緒併發標記出存活的物件。

③最終標記,同CMS回收器一致,修正在併發標記將期間使用者執行緒新產生的物件。

④篩選回收,這個階段可根據使用者期望的GC停頓時間制定回收計劃。

8. 類在JVM中的載入過程

Java檔案被編譯為Class位元組碼檔案後被載入到JVM中,主要分為三步:載入 -> 連線 -> 初始化。連線過程又分為:驗證 -> 準備 -> 解析。

9. 類是如何被載入到JVM中的

Java檔案被編譯成Class位元組碼檔案後,通過類載入器被載入到JVM中。類載入器從上往下一共有:啟動類載入器、擴充套件類載入器、應用程式類載入器、自定義類載入器。類先從自定義類載入器開始,逐層向上傳遞到啟動類載入器,當啟動類載入器不能載入時,再向擴充套件類載入器載入,這稱為雙親委派模型。

10. 類載入器的雙親委派模型有什麼好處

假設一個類首先被自定義類載入器載入,我們寫Object類時,系統中就會出現不同的Object類。為了保證在系統中始終都只有一個Object類,方法就是它們都通過啟動類載入器載入。

這是一個能給程式設計師加buff的公眾號 (CoderBuff)