Java 中的 GC -- GC基礎常識


文中討論的GC原理均基於 Sun Hotspot JVM,對於不一樣 JVM 實現可能會有不一樣。算法


1. GC (Gabage Collector) 作了什麼事情

  • 決定哪些內存須要回收(物理內存的位置)。框架

  • 決定什麼時候回收這些內存。線程

  • 決定以什麼方式(算法)回收這些內存代理

##2. GC 回收的不一樣區域code

  • 堆內存(Heap)。
  • 方法區
  • 程序計數器,虛擬機棧,本地方法棧 隨線程/方法 運行結束回收。
  • 堆外內存 GC 不負責回收。

##3. GC 回收對象 的依據 : 對象存活算法對象

  • 引用計數算法接口

    • 算法說明: 每一個對象關聯一個引用計數器,當有引用就加1,引用失效時減一,引用爲0說明對象可回收
    • 缺陷: 對象循環互相引用不能檢測,指的是,多個對象之間互相引用,可是這多個對象與其餘外界再也不具有任何訪問條件的現象
  • 根搜索算法生命週期

    • 算法說明: 從一系列 GCRoot 對象向下搜索,搜索走過的路徑叫作引用鏈,當某個對象不能經過引用鏈被搜索到,就說明可回收
    • GC Root: 1. 虛擬機棧中的引用對象 2. 方法區中靜態變量引用的對象 3. 方法區常量池引用的對象 4. 本地方法棧中引用的對象 (JNI)
  • 總結隊列

    • 大多數虛擬機採用的是跟搜索算法

##3. GC 引用的分類內存

  • 強引用

    • 說明: 使用 new 關鍵字實例化賦值的對象與變量之間的關係叫作強引用
    • 回收時機: 只要強引用存在,就永遠不會被回收
  • 軟引用

    • 說明: 描述有做用,但非必需的對象,使用 SoftReference 類來定義
    • 回收時機: 在系統發生內存溢出以前,會被歸入回收範圍以內並進行第二次回收
  • 弱引用

    • 說明: 比軟引用更弱的引用類型,使用 WeakReference 類來定義
    • 回收時機: 只能存活到下一次垃圾收集發生以前(不管時候內存溢出)
  • 虛引用

    • 說明: 最弱的引用類型,虛引用至關於對象的生命週期是透明的(不會延長對象的生命週期),甚至沒法經過虛引用得到對象的實例,惟一的目的就是在被回收的時候收到一個系統通知,使用 PhantomReference 類來定義
    • 回收時機: 至關於不存在,不影響回收時機

##3. GC 回收對象的全過程

  • 堆內存的回收

    • 回收特色: 堆內存主要回收廢棄,無用的對象
    • 回收過程:
      1. 根據存活算法掃描到某個對象A已經不被引用並進行第一次標記
      2. 第一次標記以後,篩選該對象是否有必要執行 finalize() 方法,執行的條件是該對象覆蓋了finalize() 方法,而且finalize() 方法未被調用過。
      3. 若是沒有必要執行finalize() 方法
      4. 若是有必要執行finalize()方法,該對象被放置到一個F-QUEUE隊列中,並在一個虛擬機線程去執行,執行的過程當中,只保證觸發這個方法,不保證等待方法運行結束(防止時間過長、死循環 致使GC回收機制崩潰)
      5. GC 進行第二次掃描,若是發現再次發現對象A 不被引用,那麼就將執行回收過程;這裏若是對象A在步驟 4 中執行finalize() 方法的時候,在代碼裏面從新與GCRoot引用鏈得到的訪問關係,此次掃描將不會被掃描到,可是由於finalize()已經被執行過了,因此下次一旦被掃描到,就不能再經過finalize()來GC逃逸了
  • 方法區內存的回收

    • 回收特色: 方法區內存主要回收廢棄,不用的 常量,類,接口

    • 回收常量: 加入對於某個常量池中的字符串,已經沒有任何該類型(String)的對象是這個值,也沒有其餘地方引用到了這個字面量,若是這個時候發生內存回收,並且有必要(這個根據情具體實現況判斷什麼是有必要,好比常量的生命時間,常量的使用頻率等),這個常量將被回收

    -回收類(包括它的接口,方法名,字段): 1. 該類的實例對象都已經被回收 2. 加載該類的ClassLoader也已經被回收 3. 該類的Class 對象沒有被任何地方引用,也就是沒法經過反射來訪問這個類 4. 當知足了上述3個條件,僅僅是說明能夠回收了,不表明會回收,具體看不一樣虛擬機的限定條件 5. 類回收的主要場景: 對於應用大量 反射,動態代理,CGLib 等bytecode的框架以及場景,動態生成JSP和OSGI等頻繁定義用戶ClassLoader的場景,都有可能產生大量的自動生成的類加載行爲,爲了防止永久區溢出,須要對這種生成的類進行卸載

相關文章
相關標籤/搜索