JVM堆記憶體設定

bzt820801發表於2017-08-21

  今天碰到了一個題目,講的是關於堆記憶體的問題,題目如下

  下面哪種情況會導致持久區jvm堆記憶體溢位?
A.迴圈上萬次的字串處理
B.在一段程式碼內申請上百M甚至上G的記憶體
C.使用CGLib技術直接操作位元組碼執行,生成大量的動態類
D.不斷建立物件

這個題目的答案選擇C,我在做這個題之前對於JVM的瞭解幾乎為0,所以看到這個題目基本就是隨便選了一個,甚至沒有看到原題中是持久區堆記憶體,只以為是記憶體溢位。所以在做完這個題目以後瞭解了一下JVM。

JVM是指Java虛擬機器,JVM又分為了棧,堆,方法區,本地方法棧等幾個部分,因為這個題目的緣故,重點了解了下堆。

1.棧
每一個執行緒執行的時候都會在棧申請開闢一塊棧幀。每個棧幀包括區域性變數區和運算元棧,用於存放此次方法呼叫過程中的臨時變數、引數和中間結果。
2.方法區
方法區用來存放要載入的類資訊、靜態變數、final型別的常量、屬性和方法資訊。
3,本地方法棧
本地方法棧用來支援native方法的執行,儲存每個native方法的呼叫狀態。
4.堆
程式碼中每new一個新物件,都會在堆中建立,然後下面重點了解了一下堆。

堆記憶體設定
堆分為兩部分,Permanent和head,Permanent Generation即持久帶。
head又分為Young Generation和Old Generation,即年輕代和年老代。
年輕代又分為Eden和Survivor。
Survivor又分為From和To。

年輕代
所有新建立的物件都放在新生代中,新生代的作用主要就是回收那些生命週期比較短的物件。
年老代
相對應的,老年代就存放那些生命週期比較長的物件。

這也就涉及到了垃圾回收機制。
因為年輕代中物件存活時間短,所以採用Copying演算法,簡單說就是把存活物件從一個區域拷貝到另一個區域,對應年輕代中就是Eden和From,To之間的拷貝,當觸發GC進行回收依然空間不足就回進去年老代,年老代滿了,進行Full GC,騰出的空間依然不足的話,就回出現記憶體溢位的錯誤OutOfMemory。比如開頭寫的那個題目中的ABD選項都是該原因導致的記憶體溢位。

而持久區則不同,持久區用於存放靜態型別資料,如Java Class, Method 等。持久代對垃圾回收沒有顯著影響。但是有些應用可能動態生成或呼叫一些Class,例如前面題目的C選項,在這種時候往往需要設定一個比較大的持久代空間來存放這些執行過程中動態增加的型別。

最後簡單記錄垃圾回收的一點知識
   序列GC是在整個掃描和複製過程採用單執行緒的方式來進行,適用於單CPU、新生代空間較小及對暫停時間要求不是非常高的應用上,是client級別預設的GC方式。
  並行回收GC是在整個掃描和複製過程採用多執行緒的方式來進行,適用於多CPU、對暫停時間要求較短的應用上,是server級別預設採用的GC方式。
  並行GC要與舊生代的併發GC配合使用
  舊生代的GC與新生代不同,物件存活的時間比較長,比較穩定,因此採用Mark演算法來進行回收,所謂標記就是掃描出存活的物件,然後再進行回收未被標記的物件,回收後空出的空間要麼進行合併,要麼標記出來便於下次進行分配,總之就是要減少記憶體碎片帶來的效率損耗。
 

相關文章