Java虛擬機運行時內存

1、新生代

是用來存放新生的對象。一般佔據堆的 1/3 空間。由於頻繁創建對象,所以新生代會頻繁觸發 MinorGC 進行垃圾回收。新生代又分爲 Eden 區、ServivorFrom、ServivorTo 三個區

  • Eden區
    • Java 新對象的出生地(如果新創建的對象佔用內存很大,則直接分配到老年代)。當 Eden 區內存不夠的時候就會觸發 MinorGC,對新生代區進行一次垃圾回收
  • SurvivorFrom區
    • 上一次 GC 的倖存者,作爲這一次 GC 的被掃描者
  • SurvivorTo區
    • 保留了一次 MinorGC 過程中的倖存者
  • MinorGC 的過程(複製->清空->互換)

採用複製算法

    1. eden、servicorFrom 複製到 ServicorTo,年齡+1 首先,把 Eden 和 ServivorFrom 區域中存活的對象複製到 ServicorTo 區域(如果有對象的年 齡以及達到了老年的標準,則賦值到老年代區),同時把這些對象的年齡+1(如果 ServicorTo 不 夠位置了就放到老年區);
    2. 清空 eden、servicorFrom 然後,清空 Eden 和 ServicorFrom 中的對象;
    3. ServicorTo 和 ServicorFrom 互換 最後,ServicorTo 和 ServicorFrom 互換,原 ServicorTo 成爲下一次 GC 時的 ServicorFrom 區

2、老年代

  • 主要存放應用程序中生命週期長的內存對象。
  • 老年代的對象比較穩定,所以 MajorGC 不會頻繁執行。在進行 MajorGC 前一般都先進行 了一次 MinorGC,使得有新生代的對象晉身入老年代,導致空間不夠用時才觸發。當無法找到足 夠大的連續空間分配給新創建的較大對象時也會提前觸發一次 MajorGC 進行垃圾回收騰出空間。
  • MajorGC 採用標記清除算法:首先掃描一次所有老年代,標記出存活的對象,然後回收沒有標記的對象。MajorGC 的耗時比較長,因爲要掃描再回收。MajorGC 會產生內存碎片,爲了減少內存損耗,我們一般需要進行合併或者標記出來方便下次直接分配。當老年代也滿了裝不下的 時候,就會拋出 OOM(Out of Memory)異常。

3、永久代

  • 指內存的永久保存區域,主要存放 Class 和 Meta(元數據)的信息,Class 在被加載的時候被放入永久區域,它和和存放實例的區域不同,GC 不會在主程序運行期對永久區域進行清理。所以這也導致了永久代的區域會隨着加載的 Class 的增多而脹滿,最終拋出 OOM 異常。
  • 在 Java8 中,永久代已經被移除,被一個稱爲“元數據區”(元空間)的區域所取代。元空間的本質和永久代類似,元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存。因此,默認情況下,元空間的大小僅受本地內存限制。類的元數據放入 native memory, 字符串池和類的靜態變量放入 java 堆中,這樣可以加載多少類的元數據就不再由 MaxPermSize 控制, 而由系統的實際可用空間來控制。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章