JVM GC知識(一)- GC算法

前言

每一個使用 Java 的開發者都知道 Java 字節碼是在 JRE 中運行。 JVM 則是 JRE 中的核心組成部分,承擔分析和執行 Java 字節碼的工做,而 Java 程序員一般並不須要深刻了解 JVM 運行狀況就能夠開發出大型應用和類庫。儘管如此,若是你對 JVM 有足夠了解,就會對 Java 有更好的掌握,而且能解決一些看起來簡單但又還沒有解決的問題。php

正文

JVM的運行時數據區

首先,咱們來看一下 JVM 不得不知道的體系結構,在編譯完以後的 class 文件裝載到類裝載器的運行時數據區,運行時數據區分爲五大塊,分別是方法區,堆, Java 棧,本地方法棧,程序計數器。Java棧,本地方法棧,程序計數器存儲本地方法接口,方法區和堆則存儲執行引擎,也是 GC 的做用區域。 程序員

運行時數據區

GC分代

JDK1.8以前,內存管理機制採用分代的策略:分爲新生代,老年代,永久代(JDK1.7及之前)。 面試

在這裏插入圖片描述

新生代

大體分爲 Eden 區和 Survivor 區, Survivor 區又分爲大小相同的兩部分: s0 ( FromSpace ) 和 s1 ( ToSpace )。新建的對象都是重新生代分配內存, Eden 區不足的時候,會把存活的對象轉移到 Survivor 區。當新生代進行垃圾回收時會觸發 Minor GC 。通常在Eden區分配對象,使用 TLAB( Thread Local Allocation Buffer ) 進行優化,在保存80%~90%生命週期較短的對象,GC頻率高,採用效率較高的複製算法。算法

爲什麼eden:s0:s1 = 8:1:1?

新生代的三個分區默認比例爲 8:1:1 ,JVM中規定 98% 的對象要在新生代被回收,而 s0 及 s1 只是做爲暫存區,每次GC的觸發以後必須保證其中一個區是空的,隨後兩個區互換位置,及 s0 -> s1 (from -> to),s1 -> s0 (to -> from),保證絕大部分對象在此被回收。緩存

老年代

舊生代用於存放新生代屢次回收依然存活的對象,如緩存對象。當舊生代滿了的時候就須要對舊生代進行回收,舊生代的垃圾回收稱做 Major GC。新建的對象也有可能直接在舊生代中分配,取決於具體GC的實現。GC頻率相對較低,標記,清理,壓縮算法的各類結合和優化。架構

新生代晉升老年代的條件

  1. Eden 區滿時,進行 Minor GC,當 Eden 和一個 Survivor 區中依然存活的對象沒法放入到 Survivor 中,則經過分配擔保機制提早轉移到老年代中。
  2. 若對象體積太大, 新生代沒法容納這個對象,-XX:PretenureSizeThreshold 即對象的大小大於此值, 就會繞過新生代, 直接在老年代分配, 此參數只對 Serial 及 ParNew 兩款收集器有效。
  3. 長期存活的對象將進入老年代。 虛擬機對每一個對象定義了一個對象年齡(Age)計數器。當年齡增長到必定的臨界值時,就會晉升到老年代中,該臨界值由參數:-XX:MaxTenuringThreshold 來設置。 若是對象在 Eden 出生並在第一次發生 MinorGC 時仍然存活,而且可以被 Survivor 中所容納的話,則該對象會被移動到 Survivor 中,而且設 Age = 1 ;之後每經歷一次 Minor GC ,該對象還存活的話 Age = Age+1。
  4. 動態對象年齡斷定。 虛擬機並不老是要求對象的年齡必須達到 MaxTenuringThreshold 才能晉升到老年代,若是在 Survivor 區中相同年齡(設年齡爲 age )的對象的全部大小之和超過 Survivor 空間的一半,年齡大於或等於該年齡(age)的對象就能夠直接進入老年代,無需等到 MaxTenuringThreshold 中要求的年齡。

永久代

對象經歷了屢次 Major GC 仍然沒有被回收即進入永久代,僅 JDK1.7 及以前的版本擁有。學習

判斷可回收的垃圾(GC對象)

咱們首先來看一下哪些是GC的目標,GC中使用的回收檢測算法有兩種,目前虛擬機基本上都是用可達性算法:優化

引用計數法

每一個對象有一個引用計數器,當對象被引用一次則計數器加1,當對象引用失效一次則計數器減1,對於計數器爲0的對象意味着是垃圾對象,能夠被GC回收。 cdn

在這裏插入圖片描述

可達性算法

從GC Roots做爲起點開始搜索,那麼整個連通圖中的對象便都是活對象,對於GC Roots沒法到達的對象便成了垃圾回收的對象,隨時可被GC回收。 視頻

在這裏插入圖片描述

常見垃圾回收算法-方法論

標記-清除算法

原理
標記

從根集合開始掃描,對存活的對象進行標記。

在這裏插入圖片描述

清除

掃描整個內存空間,回收未被標記的對象,使用free-list記錄可回收區域。

在這裏插入圖片描述

複製回收算法

原理
  1. 從根集合開始,經過Tracing從from中找到存活對象,拷貝到to中;
  2. from、to交換身份,下次內存分配從to開始。
    在這裏插入圖片描述

標記-整理算法

原理
標記

與標記-清除同樣

在這裏插入圖片描述

壓縮

再次掃描,並往一段滑動存活對象

在這裏插入圖片描述

標記-清除-壓縮

原理
  1. Mark-Sweep和Mark-Compact的結合
  2. 和Mark-Sweep一致,當進行屢次GC後才Compact
    在這裏插入圖片描述

By the way

有問題?能夠給我留言或私聊 有收穫?那就順手點個讚唄~

固然,也能夠到個人公衆號下「6曦軒」,

回覆「學習」,便可收到一份 【Java工程師進階架構師的視頻教程】~

回覆「面試」,能夠收到一套 【本人嘔心瀝血整理的Java面試題目】(部分目錄以下)

面試題目錄

面試題目錄

Checkit 公衆號
因爲我咧,科班出身的程序員,php,Android以及硬件方面都作過,不過最後仍是選擇專一於作 Java,因此有啥問題能夠到公衆號提問討論(技術情感傾訴均可以哈哈哈),看到的話會盡快回復,但願能夠跟你們共同窗習進步,關於服務端架構,Java 核心知識解析,職業生涯,面試總結等文章會不按期堅持推送輸出,歡迎你們關注~~~
相關文章
相關標籤/搜索