JVM內存管理和故障排除入門

JVM內存管理和故障排除入門

JVM內存管理概述

JVM提供自動內存管理功能,以免編程人員手動管理內存。新對象分配在堆內存上。甲根集由指針外部存儲器,靜態變量,線程,JNI引用和內部JVM結構。從根集直接訪問的對象必須保存在堆中。從任何可訪問對象可訪問的對象也必須位於堆中。這組對象是唯一可以被程序使用的對象。使用稱為垃圾回收(GC)的進程刪除不可訪問的對象(垃圾。可達對象被壓縮,即移動到堆中的連續空間。這很重要,否則堆會變得分散。

熱點中的代GC和內存空間

當JVM啟動時,它從操作系統請求一些內存。這個內存被分成各種空間。

JVM內存管理和故障排除入門

JDK 8之前的JVM中的內存空間

  • 獨立的泳池擁有不同年齡段的物體

  • JVM的GC是世代的,並基於以下假設:

  • 大多數物體都會死亡

  • 很少有參考從較舊的對年輕的對象

  • 有兩代物體:

  • 年輕:小而經常收集(小收集)。在閾值數量的GC中存活的物體轉移到老一代。

  • 舊:大,很少收集(主要收集=完整的GC)

  • 在JDK 8之前,還有一個永久代,用於存儲類表示和元數據,實例化字符串和類靜態。這在JDK 8和更高版本中被元空間所取代。

  • 元空間分配在本機內存中。它通過JVM選項MetaspaceSize進行管理,初始大小為MaxMetaspaceSize,最大值為MaxMetaspaceSize

  • 如果啟用UseCompressedClassPointers,則會使用2個內存區域來存儲類及其元數據 - 元空間壓縮類空間。用32位偏移量表示的64位類指針可節省空間。類元數據由存儲在壓縮類空間中的32位偏移量引用。默認情況下,壓縮類空間為1 GB。

  • 代碼緩存用於存儲由JIT(即時優化器)生成的編譯代碼,由本機內存分配並由Code Cache Sweeper管理

熱點JVM中的垃圾收集器

JVM針對不同代的對象有不同的垃圾收集方法。其中一些描述如下:

  • 年輕一代收集

  • 串行 - 停止世界(STW),複製收集器,單線程

  • ParNew - STW,複製收集器,多個GC線程

  • 並行清除 - STW,複製收集器,多個GC線程

  • 老一代收集

  • 串行舊 - STW,標記掃描 - 緊湊型收集器,單線程

  • 內容管理系統 - 大部分是併發的,低暫停

  • 並行舊壓縮採集器,多個GC線程

  • G1:專為大堆設計,並提供可預測的短暫停頓。

  • 幾代人都有不同的內存佈局

  • 所有世代相同的收藏家

JDK的GC選項

這些是傳遞給JVM的選項標誌,用於指定要使用的GC:

  • UseSerialGC:Serial + SerialOld

  • UseParNewGC:ParNew + SerialOld。在JDK 9中,將舊CMS用於CMS

  • UseConcMarkSweepGC:ParNew + CMS + SerialOld

  • 沒有堆壓實會導致碎片化。有浮動垃圾並需要更大的堆大小。

  • 可用空間維護為鏈接列表。與凹凸指針分配相比,分配開銷較大。

  • 額外的年輕收藏費用

  • CMS使用大部分時間收集老一代。在發生併發模式故障時使用SerialOld。

  • CMS與應用程序線程同時執行大部分工作。

  • 在JDK 9中棄用

  • UseParallelGC:並行清除+並行舊。

  • 最大化吞吐量。

  • 默認GC直到JDK 9

  • 兩代使用G1GC-G1

  • 針對具有大內存的多核機器的服務器樣式GC

  • 低GC在嘗試高吞吐量時以高概率暫停

  • 壓實收集器。低停頓沒有碎片

  • 更好的GC人體工程學。並行線程和一些任務與應用程序線程併發

  • 從JDK 7u4開始可用,在JDK 9中默認使用

有關調整垃圾回收器的更多詳細信息,請閱讀官方的GC調整指南

未成年人或年輕一代是如何收集的:

  1. 當年輕的伊甸園空間已滿時,可到達的對象被標記並移動到ToSurvivorSpace

  2. 可以訪問FromSurvivor空間中的對象將移至ToSurvivorSpace

  3. 已經越過閾值的FromSurvivor空間中的對象被提升為舊一代

  4. 伊甸園變得空無一人,為新的分配做好準備

  5. 往返於倖存者空間切換

關於Mark-Sweep-Compact收集器的注意事項(Serial Old):

  • 標記階段:標記所有活物

  • 掃描階段:掃過堆確定垃圾

  • 滑動階段:GC通過將活動對象滑動到堆的開始位置來執行滑動壓實


分享到:


相關文章: