JAVA-GC機制

#1、GC基本原理 GC(Garbage Collection),是JAVA/.NET中的垃圾收集器。
Java是由C++發展來的,它擯棄了C++中一些繁瑣容易出錯的東西,引入了計數器的概念,其中有一條就是這個GC機制(C#借鑑了JAVA)。程序員

編程人員容易出現問題的地方,忘記或者錯誤的內存回收會致使程序或系統的不穩定甚至崩潰,Java提供的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操做方法。因此,Java的內存管理實際上就是對象的管理,其中包括對象的分配和釋放。算法

對於程序員來講,分配對象使用new關鍵字;釋放對象時,只要將對象全部引用賦值爲null,讓程序不可以再訪問到這個對象,咱們稱該對象爲"不可達的".GC將負責回收全部"不可達"對象的內存空間。編程

對於GC來講,當程序員建立對象時,GC就開始監控這個對象的地址、大小以及使用狀況。一般,GC採用有向圖的方式記錄和管理堆(heap)中的全部對象。經過這種方式肯定哪些對象是"可達的",哪些對象是"不可達的".當GC肯定一些對象爲"不可達"時,GC就有責任回收這些內存空間。可是,爲了保證 GC可以在不一樣平臺實現的問題,Java規範對GC的不少行爲都沒有進行嚴格的規定。例如,對於採用什麼類型的回收算法、何時進行回收等重要問題都沒有明確的規定。所以,不一樣的JVM的實現者每每有不一樣的實現算法。這也給Java程序員的開發帶來行多不肯定性。本文研究了幾個與GC工做相關的問題,努力減小這種不肯定性給Java程序帶來的負面影響。網絡

#2、GC分代劃分 JVM內存模型中Heap區分兩大塊,一塊是 Young Generation,另外一塊是Old Generation 。
輸入圖片說明函數

  1. 在Young Generation中,有一個叫Eden Space的空間,主要是用來存放新生的對象,還有兩個Survivor Spaces(from、to),它們的大小老是同樣,它們用來存放每次垃圾回收後存活下來的對象。
  2. 在Old Generation中,主要存放應用程序中生命週期長的內存對象。
  3. 在Young Generation塊中,垃圾回收通常用Copying的算法,速度快。每次GC的時候,存活下來的對象首先由Eden拷貝到某個SurvivorSpace,當Survivor Space空間滿了後,剩下的live對象就被直接拷貝到OldGeneration中去。所以,每次GC後,Eden內存塊會被清空。
  4. 在Old Generation塊中,垃圾回收通常用mark-compact的算法,速度慢些,但減小內存要求。
  5. 垃圾回收分多級,0級爲所有(Full)的垃圾回收,會回收OLD段中的垃圾;1級或以上爲部分垃圾回收,只會回收Young中的垃圾,內存溢出一般發生於OLD段或Perm段垃圾回收後,仍然無內存空間容納新的Java對象的狀況。

#3、增量式GC 增量式GC(Incremental GC),是GC在JVM中一般是由一個或一組進程來實現的,它自己也和用戶程序同樣佔用heap空間,運行時也佔用CPU。性能

當GC進程運行時,應用程序中止運行。所以,當GC運行時間較長時,用戶可以感到Java程序的停頓,另一方面,若是GC運行時間過短,則可能對象回收率過低,這意味着還有不少應該回收的對象沒有被回收,仍然佔用大量內存。所以,在設計GC的時候,就必須在停頓時間和回收率之間進行權衡。一個好的GC實現容許用戶定義本身所須要的設置,例若有些內存有限的設備,對內存的使用量很是敏感,但願GC可以準確的回收內存,它並不在乎程序速度的快慢。另一些實時網絡遊戲,就不可以容許程序有長時間的中斷。 增量式GC就是經過必定的回收算法,把一個長時間的中斷,劃分爲不少個小的中斷,經過這種方式減小GC對用戶程序的影響。雖然,增量式GC在總體性能上可能不如普通GC的效率高,可是它可以減小程序的最長停頓時間。.net

Sun JDK提供的HotSpot JVM就能支持增量式GC。HotSpot JVM缺省GC方式爲不使用增量GC,爲了啓動增量GC,咱們必須在運行Java程序時增長-Xincgc的參數。 HotSpot JVM增量式GC的實現是採用Train GC算法,它的基本想法就是:將堆中的全部對象按照建立和使用狀況進行分組(分層),將使用頻繁高和具備相關性的對象放在一隊中,隨着程序的運行,不斷對組進行調整。當GC運行時,它老是先回收最老的(最近不多訪問的)的對象,若是整組都爲可回收對象,GC將整組回收。這樣,每次GC運行只回收必定比例的不可達對象,保證程序的順暢運行。設計

#4、finalize finalize 是位於Object類的一個方法code

protected void finalize() throws Throwable { }

該方法的訪問修飾符爲protected,因爲全部類爲Object的子類,所以用戶類很容易訪問到這個方法。對象

因爲,finalize函數沒有自動實現鏈式調用,咱們必須手動的實現,所以finalize函數的最後一個語句一般是 super.finalize()。經過這種方式,咱們能夠實現從下到上實現finalize的調用,即先釋放本身的資源,而後再釋放父類的資源。根據Java語言規範,JVM保證調用finalize函數以前,這個對象是不可達的,可是JVM不保證這個函數必定會被調用。另外,規範還保證finalize函數最多運行一次。

不建議使用finalize:

  • GC爲了可以支持finalize函數,要對覆蓋這個函數的對象做不少附加的工做。
  • 在finalize運行完成以後,該對象可能變成可達的,GC還要再檢查一次該對象是不是可達的。所以,使用 finalize會下降GC的運行性能。
  • 因爲GC調用finalize的時間是不肯定的,所以經過這種方式釋放資源也是不肯定的。

一般,finalize用於一些不容易控制、而且很是重要資源的釋放,例如一些I/O的操做,數據的鏈接。這些資源的釋放對整個應用程序是很是關鍵的。在這種狀況下,程序員應該以經過程序自己管理(包括釋放)這些資源爲主,以finalize函數釋放資源方式爲輔,造成一種雙保險的管理機制,而不該該僅僅依靠finalize來釋放資源。

#5、強引用、弱引用、軟引用、虛引用 Java 4種引用的級別由高到低依次爲:
強引用 > 軟引用 > 弱引用 > 虛引用

四種引用在垃圾回收時的區別:
輸入圖片說明

參考文獻:

https://my.oschina.net/ydsakyclguozi/blog/404389
http://blog.csdn.net/ithomer/article/details/6252552

相關文章
相關標籤/搜索