垃圾回收簡介
1.JVM
下面圖片總結了JVM的關鍵組件。在JVM體系結構中,與垃圾回收相關的兩個主要組件是堆內存和垃圾回收器。堆內存是內存數據區,用來保存運行時的對象實例。垃圾回收器也會在這裏操作。現在我們知道這些組件是如何在框架中工作的。
2.Java堆內存
我們有必要了解堆內存在JVM內存模型的角色。在運行時,Java的實例被存放在堆內存區域。當一個對象不再被引用時,滿足條件就會從堆內存移除。在垃圾回收進程中,這些對象將會從堆內存移除並且內存空間被回收。堆內存以下三個主要區域:
- 新生代(Young Generation)
- Eden空間(Eden space,任何實例都通過Eden空間進入運行時內存區域)
- S0 Survivor空間(S0 Survivor space,存在時間長的實例將會從Eden空間移動到S0 Survivor空間)
- S1 Survivor空間 (存在時間更長的實例將會從S0 Survivor空間移動到S1 Survivor空間)
- 老年代(Old Generation)實例將從S1提升到Tenured(終身代)
- 永久代(Permanent Generation)包含類、方法等細節的元信息(java8已移除)
永久代空間在Java SE8特性中已經被移除。
垃圾回收機制工作:
Java 垃圾回收是一項自動化的過程,用來管理程序所使用的運行時內存。通過這一自動化過程,JVM 解除了程序員在程序中分配和釋放內存資源的開銷。
垃圾回收是一種回收無用內存空間並使其對未來實例可用的過程
Eden 區:當一個實例被創建了,首先會被存儲在堆內存年輕代的 Eden 區中
Survivor 區(S0 和 S1):作爲年輕代 GC(Minor GC)週期的一部分,存活的對象(仍然被引用的)從 Eden 區被移動到 Survivor 區的 S0 中。類似的,垃圾回收器會掃描 S0 然後將存活的實例移動到 S1 中。
死亡的實例(不再被引用)被標記爲垃圾回收。根據垃圾回收器選擇的不同,要麼被標記的實例都會不停地從內存中移除,要麼回收過程會在一個單獨的進程中完成。
老年代: 老年代(Old or tenured generation)是堆內存中的第二塊邏輯區。當垃圾回收器執行 Minor GC 週期時,在 S1 Survivor 區中的存活實例將會被晉升到老年代,而未被引用的對象被標記爲回收。
老年代 GC(Major GC):相對於 Java 垃圾回收過程,老年代是實例生命週期的最後階段。Major GC 掃描老年代的垃圾回收過程。如果實例不再被引用,那麼它們會被標記爲回收,否則它們會繼續留在老年代中。
內存碎片:一旦實例從堆內存中被刪除,其位置就會變空並且可用於未來實例的分配。這些空出的空間將會使整個內存區域碎片化。爲了實例的快速分配,需要進行碎片整理。
垃圾回收中實例的終結
在釋放一個實例和回收內存空間之前,Java 垃圾回收器會調用實例各自的 finalize() 方法,從而該實例有機會釋放所持有的資源。雖然可以保證 finalize() 會在回收內存空間之前被調用,但是沒有指定的順序和時間。多個實例間的順序是無法被預知,甚至可能會並行發生。程序不應該預先調整實例之間的順序並使用 finalize() 方法回收資源。
- 任何在 finalize過程中未被捕獲的異常會自動被忽略,然後該實例的 finalize 過程被取消。
- JVM 規範中並沒有討論關於弱引用的垃圾回收機制,也沒有很明確的要求。具體的實現都由實現方決定。
- 垃圾回收是由一個守護線程完成的。
垃圾回收器的種類:
- 串行垃圾回收器(Serial Garbage Collector)-XX:+UseSerialGC
- 並行垃圾回收器(Parallel Garbage Collector)
- 併發標記掃描垃圾回收器(CMS Garbage Collector)XX:+USeParNewGC XX:+UseConMarkSweepGC
- G1垃圾回收器(G1 Garbage Collector) –XX:+UseG1GC
Java 8 的新特性
在使用G1垃圾回收器的時候,通過 JVM參數 -XX:+UseStringDeduplication 。 我們可以通過刪除重複的字符串,只保留一個char[]來優化堆內存。這個選擇在Java 8 被引入。
----------------------------------------------------------------