JVM(二)——GC

  • 引用類型

    • 強引用:類似Object o=new Object()這種引用。只要強引用還存在,對象不會被回收。

    • 軟引用:對於軟引用關聯的對象,在系統將要發生內存溢出前,會被納入回收範圍,並進行第二次回收。

    • 弱引用:被弱引用關聯的對象只能生存到下一次回收之前。無論內存是否足夠都會被回收。

    • 虛引用:不會影響對象生存時間,也無法獲得對象實例,對其唯一期望是關聯的實例在被回收時收到一個系統通知。

  • 對象回收

    • 引用計數法(Reference Counting)

      • 給對象中添加一個引用計數器,被引用時+1,失效時-1。任何時刻引用計數爲0則對象不可再使用。 這種算法很難應對循環引用的情況。

    • 根搜索算法(GC Roots Tracing)

      • 當一個對象到GC Roots不可達時,證明此對象是不可用的。根搜索算法中,無法到達的對象並非立即回收,而是被標記一次後進行篩選,篩選的條件是此對象是否有必要執行finaliz()方法。存在該方法(未被調用 過)的對象,將被放置在名爲F-Queue的隊列,並在稍後有虛擬機建立一個低優先級的Finalizer線程執行(虛擬機不承諾該方法執行結束,不一定 會執行), 稍後GC將對F-Queue進行第二次小規模標記,如果此時發現對象可達,將被移出即將回收集合。

      • 可作爲GC根的對象包括

        • 虛擬機棧(中局部變量表)中引用的對象。

        • 方法區中類靜態屬性引用的對象。

        • 方法區中常量引用的對象。

        • 本地方法中JNI(java本地方法)的引用對象。

  • 方法區回收

    • 廢棄常量:與堆中實例回收類似(常量池中類、接口、方法、字段的符號引用也類似)。

    • 無用的類:堆中沒有該類實例——加載該類的Classloader已被回收,該類對應的java.lang.Class對象沒有引用,無法通過反射訪問。

    • 大量使用反射、動態代理、CGLib等bytecode框架的場景,以及動態生成jsp或者osgi這類頻繁自定義Classloader的場景都需要該功能

  • 垃圾回收算法

    • 標記-清除算法(Mark-Sweep)

      • 算法:首先標記所有需要回收的對象,在標記完成後,統一回收所有被標記對象。

      • 優點:不存在循環引用問題。

      • 缺點:效率不高,會產生大量不連續內存碎片。

    • 複製算法(Copying)

      • 算法:將可用內存分爲兩塊,每次只使用一塊,回收時將此塊內存中還生存的對象複製到另一塊,把已使用的內存清理掉。

      • 優點:不會出現碎片問題。

      • 缺點:浪費。對象存活率較高時,效率降低。

    • 標記-整理算法(Mark-Compact)

      • 算法:與標記-清除算法類似,只是不直接回清除,而是讓所有對象向一端移動,然後清理掉端邊界以外的內存。

    • 分代收集算法(Genrerational Collection)

      • 算法:根據對象存活週期劃分內存爲幾塊,一般是把堆分爲新生代和老年代,根據各個時代不同,採用不同算法。

  • 垃圾收集器

    • 示意圖

wKiom1fXnbSRPACjAABwjR_8_rM638.png

    • Serial

      • 單線程垃圾收集器,運行時停止其他線程直到GC結束。

      • 新生代:複製算法。

      • 老年代:標記-整理算法。

    • ParNew

      • Serial的多線程版本。

      • 新生代:複製算法。並行。

      • 老年代:標記-整理算法。串行。

    • Parallel Scavenge

      • 新生代收集器,使用複製算法。並行。類似ParNew收集器,此收集器更關注系統的吞吐量。可以通過參數來打開自適應調節策略,虛擬機會根據當前系統的運行情況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或最大的吞吐量;也可以通過參數控制GC的時間不大於多少毫秒或者比例。

    • Serial Old

      • 老年代收集器,使用標記-整理算法。串行。

    • Parallel Old

      • Parallel Scavenge的老年代版本。使用標記-整理算法。並行。

    • Cms

      • 以獲取最短回收停頓時間爲目標的收集器。標記-清除算法。

      • 步驟:

        • 初始標記:快速標記GC根能連接的對象。

        • 併發標記:根搜索,標記待回收。

        • 重新標記:應對標記期間變動的對象的標記記錄。

        • 併發清除:回收。

      • CPU敏感。

      • 無法處理浮動垃圾:一些在本次GC過程中生成的數據,只能留待下一次GC。如果GC過程中預留內存無法滿足,會拋出Concurrent Mode Failure後,啓動Serial Old進行老年代垃圾收集。

      • 標記-清除算法會產生大量空間碎片,在無法爲對象找到足夠的連續空間時,會觸發Full GC。

    • G1

      • 基於標記-整理算法實現,可以精確控制停頓。

  • 內存分配與回收策略

    • 優先在eden分配。大對象直接進入老年代。長期存活對象將進入老年代。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章