Java 記憶體模型中,程序計數器、虛擬機棧、本地方法棧隨線程生滅,棧幀隨方法出棧自動釋放,無需 GC 介入。
GC 核心針對:堆、方法區(類信息、常量、靜態變量)。這兩區內存分配動態,只有運行時才知創建哪些對象。
對象添加引用計數器,引用+1,釋放-1。
致命缺陷:無法處理循環引用(A→B,B→A,外部無引用,計數器永不歸零)。
以 GC Roots 為起點(棧局部變量、方法區靜態屬性/常量、本地方法棧 JNI 引用等),向下搜索引用鏈。
不可達對象 = 垃圾。採用 Dijkstra 著色算法(白/灰/黑),時間複雜度 O(n)。
標記垃圾 → 直接清除。
缺點:內存碎片化,大對象分配困難。
內存劃分為兩塊,每次只用一塊。GC 時將存活對象複製到另一塊,清空已用塊。
優點:無碎片、分配指針碰撞極快。
缺點:空間利用率 50%。
現代商業 JVM 新生代優化:Eden:Survivor = 8:1:1,實際可用 90%。
標記垃圾 → 清除 → 存活對象向一端移動整理。
優點:無碎片、空間利用率高。
缺點:移動對象需更新引用,速度最慢,難以並發。
基於弱代假說:
① 大多數對象朝生夕死
② 熬過多次 GC 的對象難以消亡
堆劃分:
| 收集器 | 作用代 | 算法 | 線程 | 特點 |
|---|---|---|---|---|
| Serial | 新生代 | 複製 | 單 | Client默認,簡單高效 |
| ParNew | 新生代 | 複製 | 多 | Serial多線程版,唯一配CMS |
| Parallel Scavenge | 新生代 | 複製 | 多 | 關注吞吐量,自適應調節 |
| Serial Old | 老年代 | 標記-整理 | 單 | Client老年代默認 |
| Parallel Old | 老年代 | 標記-整理 | 多 | 配合Parallel Scavenge |
| CMS | 老年代 | 標記-清除 | 多(並發) | 低停頓,碎片、浮動垃圾、CPU敏感 |
| G1 | 整堆(Region) | 標記-整理+複製 | 多(並發+並行) | 可預測停頓,大堆首選 |
回收價值 = 可回收空間 / 回收耗時 排序,優先回收高價值 Region