1.原因
JVM在程序運行過程當中,會創建大量的對象,這些對象,大部分是短周期的對象,小部分是長周期的對象,對于短周期的對象,需要頻繁地進行垃圾回收以保證無用對象盡早被釋放掉,對于長周期對象,則不需要頻率垃圾回收以確保無謂地垃圾掃描檢測。為解決這種矛盾,Sun JVM的內存管理采用分代的策略。
2.新生代、老年代與持久代
2.1 年輕代 (Young Gen)
新生代主要用于存放新創建的對象,內存大小相對會比較小,垃圾回收會比較頻繁。
新生代被分為1個Eden和兩個Survivor (From Survior 和 To Survivor),當對象在堆創建時,會進入Eden,垃圾收集器進行回收時會掃描Eden和From Survivor,如果對象仍然存活,則復制到To Survivor ,如果To Survivor已滿,則復制到
Old Gen(老年代)。同時,在垃圾收集器幾次掃描Survivor空間發現對象仍然存活,則認為該對象應該被持久化,將其移動到Old Gen(老年代)。掃描完畢后jvm會將Eden和From Survivor清空,然后交換兩個Survivor(即原來的From Survivor變為
To Survivor ,原來的To Survivor 變為 From Survivor),這樣做的目的是減少內存碎片的產生。
我們可以總結出:新生代進行垃圾回收時,采用標記-復制算法避免產生內存碎片,采用空間換時間的方式來加速內存中不被使用的對象回收。
2.2 老年代
老年代主要用來存放jvm認為生命周期比較長的對象(經過幾次新生代垃圾收集還存活的對象),內存大小相對比較大,同時垃圾回收也沒有那么頻繁。老年代主要采用壓縮的方式來避免內存碎片(將存活的對象移動到內存的一邊)。
2.3 持久代
持久代主要存放類定義、字節碼和常量等很少會變更的信息。
若垃圾收集器依據這種小幅度的調整收集不能騰出足夠的空間,就會運行Full GC,此時JVM GC停止所有在堆中運行的線程并執行清除動作。