處理多代對象

Java 垃圾收集器實現了分代垃圾收集策略,可以按年齡對對象進行分類。

JVM 中的這種需要(標記和壓縮所有對象)可以稱為低效。由於分配了大量對象,因此它們的列表會增長,從而導致垃圾收集時間增加。對應用程序的實證分析表明,Java 中的大多數對像都是短暫的。

JVM中的堆內存區分為三部分:

處理多代對象

年輕一代

新創建的對像從年輕一代開始。年輕一代進一步細分為兩類。

  • Eden Space - 所有新對像都從這裡開始,它們被分配初始內存。
  • 倖存者空間(FromSpace 和 ToSpace)——對像在一個垃圾收集週期後從 Eden 移動到這裡。

從年輕代收集對象的過程稱為次要垃圾收集事件。

當 Eden 的空間充滿對象時,將執行小型垃圾收集。所有死物體都被移除,所有活物體都被移動到剩下的兩個空間之一。小型 GC 還會檢查倖存者空間中的對象並將它們移動到另一個(下一個)倖存者空間。

讓我們以下面的序列為例。

  1. 伊甸園中有兩種類型的物體(活的和死的)。
  2. 發生小型 GC - 所有死對像都從伊甸園中移除。所有有生命的物體都被移動到 space-1 (FromSpace)。Eden 和 space-2 現在是空的。
  3. 新對像被創建並添加到伊甸園。Eden 和 space-1 中的一些物體變得死了。
  4. 發生小型 GC - 所有死對像都從 Eden 和 space-1 中刪除。所有有生命的物體都被移動到空間 2 (ToSpace)。Eden 和 space-1 是空的。

因此,在任何時候,其中一個倖存者空間總是空的。當倖存者達到通過倖存者空間移動的某個閾值時,他們會前進到老一代。

您可以使用-Xmn標誌來設置新生代的大小。

老一代

存在很長一段時間(例如,程序生命週期的大部分時間)的對象最終會變成更老的對象——百歲老人。它也被稱為常規生成,包含長期留在 Survivor Spaces 中的對象。

一個對象的生存期閾值決定了它在被移動到老年代之前必須經歷多少個垃圾收集週期。對像從老年代發送到垃圾中的過程稱為主垃圾回收事件。

您可以使用-Xms-Xmx標誌來設置初始和最大堆內存大小。

因為 Java 使用分代垃圾收集,對象經歷的垃圾收集事件越多,它在堆上移動的越遠。他從年輕一代開始,如果他活得足夠長,最終會在普通一代結束。

要了解對像在空間和世代之間的提升,請考慮以下示例:

當一個對像被創建時,它首先被放置在年輕代的伊甸園空間中​​。

一旦發生小型垃圾回收,Eden 中的活動對象就會被移動到 FromSpace。當下一次次要垃圾回收發生時,Eden 和空間中的活動對像都被移動到 ToSpace。

這個循環持續一定次數。如果該對像在此之後仍在“服務中”,則下一個垃圾收集週期會將其移至老年代空間。

永久代和元空間

類和方法等元數據存儲在持久代中。JVM 根據應用程序使用的類在運行時填充它。不再使用的類可以從永久代變成垃圾。

您可以使用-XX:PermGen-XX:MaxPermGen標誌來設置永久代的初始大小和最大大小。

元空間

從 Java 8 開始,PermGen 空間被 MetaSpace 內存空間取代。該實現與 PermGen 不同——此堆空間現在會自動更改。

這避免了應用程序由於 PermGen 的堆空間大小有限而出現的內存不足問題。元空間內存可以被垃圾回收,當元空間達到最大大小時,不再使用的類將被自動清理。