1. 程式人生 > >JVM年輕代,老年代,永久代詳解

JVM年輕代,老年代,永久代詳解

前言

最近被問到了這個問題,解釋的不是很清晰,有一些概念略微模糊,在此進行整理和記錄,分享給大家。本篇文章主要講解記憶體區域的年輕代,老年代和永久代,略微提及一些垃圾回收演算法,下面是正文。

堆整體

堆主要用於存放各種類的例項物件和陣列。在java中被分為兩個區域:年輕代和老年代。在java中還有一個永久代的意思,這裡最後會單獨說明。

年輕代和老年代的劃分是為了更好的記憶體分派及回收。提高效率。
堆是垃圾回收機制的重點區域。我們知道垃圾回收機制有三種,minor gc,major gc 和full gc。針對於堆的就是前兩種。年輕代的叫 minor gc,老年代的叫major gc。

年輕代

年輕代用來存放新近建立的物件,尺寸隨堆大小的增加和減少而相應的變化,預設值是保持為堆的1/15。
年輕代的大小可以通過-xmn設定固定大小,也可以通過-xx:newratio設定年輕代和年老代的比例。
年輕代中存在的物件是死亡非常快的。存在朝生夕死的情況。
所以為了提高年輕代的垃圾回收效率,又將年輕代劃分為三個區域,一個eden和兩個sunrvivor from。

eden和survivor預設比例是8:1:1,進行垃圾回收採用的是分代複製演算法。每次新生代的使用,會是eden區和一塊survivor區。當我們進行垃圾回收的時候,清除正在使用的區域,將其中的存貨物件,放入到另一個survivor區域,並進行整理,保證空間的連續。如果物件長時間存活,則將物件移動到老年區。存活下來的物件,他的年齡會增長1。當物件的年齡一次次存活,一次次增長,到達15的時候,這些物件就會移步到老年代。在年輕代執行gc的時候,如果老年代的連續空間小於新生代物件的總大小,就會觸發一次full gc。是為了給新生代做擔保,保證新生代的老年物件可以順利的進入到老年代的記憶體區。

老年代

老年代中存放的物件是存活了很久的,年齡大於15的物件。在老年代觸發的gc叫major gc也叫full gc。full gc會包含年輕代的gc。但老年代只要執行gc就一定是full gc。
full gc採用的是標記-清除演算法。會產生記憶體碎片。在執行full gc的情況下,會阻塞程式的正常執行。老年代的gc比年輕代的gc效率上慢10倍以上。對效率有很大的影響。

永久代

永久代是hotspot虛擬機器,也就是我們使用的java虛擬機器的特有的概念,他不屬於堆記憶體,是方法區的一種實現,各大廠商對方法區有各自的實現。永久代存放jvm執行時,需要的類,包含java庫的類和方法,在觸發full gc的情況下,永久代也會被進行垃圾回收。永久代的記憶體溢位也就是 pergen space。

元空間

元空間是metaspace,在jdk1.8的時候,jvm移除了永久代的概念,元空間也是對java虛擬機器的方法區的一種實現。元空間與永久代最大的區別在於,元空間不在虛擬機器中,使用本地記憶體。通過配置如下引數可以更改元空間的大小。
-XX:MetaspaceSize:初始空間的大小。達到該值就會觸發垃圾收集進行型別解除安裝,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低該值;如果釋放了很少的空間,那麼在不超過MaxMetaspaceSize時,適當提高該值。
-XX:MaxMetaspaceSize,最大空間,預設是沒有限制的。
永久代的回收會隨著full gc進行移動,消耗效能。每種型別的垃圾回收都需要特殊處理元資料。將元資料剝離出來,簡化了垃圾收集,提高了效率