程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Java中的垃圾回收,Java垃圾回收

Java中的垃圾回收,Java垃圾回收

編輯:JAVA綜合教程

Java中的垃圾回收,Java垃圾回收


關於垃圾回收,主要是兩個步驟:

垃圾對象的判斷方法

那麼,哪些對象可以被認為是“GC Roots”對象呢,如下

  • Class - 由系統類加載器加載的對象,這些類是不能夠被回收的,他們可以以靜態字段的方式保存持有其它對象。
  • Thread - 活著的線程
  • Stack Local - Java方法的local變量或參數
  • JNI Local - JNI方法的local變量或參數
  • JNI Global - 全局JNI引用
  • Monitor Used - 用於同步的監控對象
  • Held by JVM - 用於JVM特殊目的由GC保留的對象,但實際上這個與JVM的實現是有關的。可能已知的一些類型是:系統類加載器、一些JVM知道的重要的異常類、一些用於處理異常的預分配對象以及一些自定義的類加載器等。然而,JVM並沒有為這些對象提供其它的信息,因此就只有留給分析分員去確定哪些是屬於"JVM持有"的了。

垃圾對象的回收方法

先來看下垃圾回收的三種算法

復制算法

將可用內存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊的內存用完了,就將還存活著的對象復制到另外一塊上面,然後再把已使用過的內存空間一次清理掉。

“標記-清除”(Mark-Sweep)算法

首先標記出所有需要回收的對象,在標記完成後統一回收所有被標記的對象;

它主要有兩個不足:一個是效率問題,標記和清除兩個過程的效率都不高;另一個是空間問題,標記清除之後會產生大量不連續的內存碎片;

標記-整理算法

標記過程仍然與“標記-清除”算法一樣,但後續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然後直接清理掉端邊界以外的內存。

那麼,垃圾對象是如何回收的呢?答案是分代回收。

分代回收策略

  不同的對象的生命周期是不一樣的。因此,不同生命周期的對象可以采取不同的收集方式,以便提高回收效率。分代垃圾回收采用分治的思想,進行代的劃分,把不同生命周期的對象放在不同代上,不同代上采用最適合它的垃圾回收方式進行回收。

  一般,Java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當的收集算法。

  在新生代中,有大批對象死去,只有少量存活,一般選用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。新生代分三個區。一個Eden區,兩個Survivor區(救助空間,一般而言)。大部分對象在Eden區中生成,當Eden區滿時,還存活的對象將被復制到Survivor區(兩個中的一個);新創建的對象的內存都分配自eden,Minor collection的過程就是將eden和在survivor space中的活對象copy到空閒survivor space中,對象在新生代裡經歷了一定次數(可以通過參數配置)的minor collection後,就會被移到老年代中,稱為tenuring。

  老年代中因為對象存活率高,不需要大量清理或整理,因此使用“標記—清理”或者“標記—整理”算法來進行回收。

  GC分為兩種,Scavenge GC和Full GC;

  • Scavenge GC:對Eden區域進行GC,清除非存活對象,並且把尚且存活的對象移動到Survivor區。
  • Full GC:對整個堆進行GC,包括Young、Tenured和Perm。在對JVM調優的過程中,很大一部分工作就是對於FullGC的調節。盡可能減少Full GC的次數

  有如下原因可能導致Full GC:

  • 年老代(Tenured)被寫滿
  • 持久代(Perm)被寫滿
  • System.gc()被顯示調用
  • 上一次GC之後Heap的各域分配策略動態變化

 

參考:

《深入理解Java虛擬機》

http://blog.csdn.net/fenglibing/article/details/8928927

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved