Dalvik VM 的堆管理與垃圾回收是 Android 系統效能優化的關鍵。本文剖析 Zygote 孵化機制、Copy-on-Write 堆分離、並行標記清除演算法與 Card Table 優化。
Zygote 孵化與 COW 堆分離
- 系統啟動 → Zygote 進程建立首個 Dalvik VM,維護單一堆。
- 應用進程由 Zygote
fork() 產生,各自持有獨立 VM。
- COW 策略:初始共享同一堆;任一方寫入時,內核複製頁面。為減少複製,堆分為:
- Zygote 堆:預載類、資源、物件,佔用部分,fork 時複製給子進程,後續極少寫入,長期共享。
- Active 堆:剩餘空間,雙方新物件皆在此分配,隔離寫入操作。
Mark-Sweep GC 兩階段
- Mark:從 GC Roots 遞歸標記可達物件。
- Sweep:回收未標記物件記憶體。
雙 Bitmap 並行標記優化
- Live Bitmap:記錄上輪 GC 存活物件。
- Mark Bitmap:記錄本輪 GC 可達物件。
- 僅需回收「Live=1 且 Mark=0」物件,避免全堆掃描。
Concurrent GC:Stop-The-World 最小化
標記階段分兩步:
- Root Set 掃描(獨佔):僅標記全域變數、堆疊、暫存器直接引用的物件,禁止其他執行緒運行。
- 遞歸標記(並行):從 Root Set 展開標記其餘物件,允許應用執行緒並行。修改記錄於 Card Table(每卡 1 byte,dirty/clean)。
第二步結束後,GC 執行緒獨佔重掃描 dirty cards,因數量極少,耗時極短。部分 GC 僅掃描 Active 堆,Card Table 專記錄 Zygote 堆物件對 Active 堆的引用變更。
此設計在保證正確性前提下,將停頓時間壓縮至毫秒級,支撐 Android 流暢體驗。