Java堆內存分區及各自特點
Java堆內存主要分為新生代(Young Generation)和老年代(Old Generation),其中新生代又進一步分為Eden區和兩個Survivor區(From和To)。這種分區設計是為了優化垃圾回收效率,基於對象生命週期的不同特性。
1. Eden區(伊甸園)
特點:
- 對象初始分配區域:新創建的對象(除了大對象)首先被分配到Eden區
- 空間佔比:在默認的內存分配比例中,Eden區通常佔新生代的80%空間
- 頻繁GC:垃圾收集頻率最高,因為大多數對象都是朝生夕死的
- 內存分配策略:使用指針碰撞(Bump the Pointer)方式進行快速內存分配
工作機制:
- 當Eden區空間不足時,觸發Minor GC(新生代垃圾回收)
- GC後,存活的對象會被複制到一個Survivor區(From或To)
- 經過Minor GC後,Eden區會被清空
2. Survivor From區和Survivor To區
特點:
- 大小相同:兩個Survivor區大小完全相同,默認各佔新生代的10%空間
- 角色互換:在垃圾回收過程中,兩個區域的角色會互換,始終保持一個為空(To區)
- 年齡計數:對象每經歷一次Minor GC仍存活,年齡計數器加1
- 對象晉升通道:作為Eden區和老年代之間的緩衝區
工作機制:
- 在GC開始時,一個為From區(非空),一個為To區(為空)
- GC過程中,Eden區和From區中存活的對象會被複制到To區
- 複製完成後,From區和Eden區被清空
- 兩個區域角色互換:原來的To區變為新的From區,原來的From區變為新的To區
- 當對象的年齡達到閾值(默認為15)時,會被晉升到老年代
3. 老年代(Old Generation)
特點:
- 存儲空間大:通常佔整個堆內存的2/3左右
- 存儲長生命週期對象:存放經歷多次GC仍存活的對象
- GC頻率低:老年代GC(Major GC/Full GC)頻率明顯低於Minor GC
- 內存分配策略:使用空閒列表(Free List)方式分配內存
工作機制:
- 對象晉升:新生代對象年齡達到閾值後進入老年代
- 大對象直接進入:超過一定大小的對象可能直接在老年代分配(避免頻繁GC)
- 空間分配擔保:當Minor GC時,如果Survivor空間不足,對象可能提前進入老年代
- 老年代GC:當老年代空間不足時,觸發Major GC或Full GC,回收效率較低
分區設計的優勢
- 分代收集:根據對象生命週期特點採用不同的GC策略,提高回收效率
- 複製算法優化:新生代使用複製算法,效率高且不會產生內存碎片
- 減少Full GC:通過Survivor區的緩衝,延長對象進入老年代的時間,減少Full GC的觸發頻率
- 內存分配高效:針對不同區域採用不同的內存分配策略,優化分配性能
典型的內存比例配置
- 默認比例:Eden : Survivor From : Survivor To = 8:1:1
- 整個堆內存中,新生代與老年代的默認比例為1:2
-
這些比例可以通過JVM參數(如-XX:SurvivorRatio、-XX:NewRatio)進行調整