JAVA的垃圾回收機制

2.1 觸發GC(Garbage Collector)的條件

    1)GC在優先級最低的線程中運行,一般在應用程序空閒即沒有應用線程在運行時被調用。但下面的條件例外。

    2)Java堆內存不足時,GC會被調用。當應用線程在運行,並在運行過程中創建新對象,若這時內存空間不足,JVM就會強制調用GC線程。若GC一次之後仍不能滿足內存分配,JVM會再進行兩次GC,若仍無法滿足要求,則JVM將報“out of memory”的錯誤,Java應用將停止。

 

  2.2 兩個重要方法

    2.2.1 System.gc()方法

      使用System.gc()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請求Java的垃圾回收。在命令行中有一個參數-verbosegc可以查看Java使用的堆內存的情況,它的格式如下:java -verbosegc classfile    由於這種方法會影響系統性能,不推薦使用,所以不詳訴。

 

    2.2.2 finalize()方法

      在JVM垃圾回收器收集一個對象之前,一般要求程序調用適當的方法釋放資源,但在沒有明確釋放資源的情況下,Java提供了缺省機制來終止該對象心釋放資源,這個方法就是finalize()。它的原型爲:protected void finalize() throws Throwable   在finalize()方法返回之後,對象消失,垃圾收集開始執行。原型中的throws Throwable表示它可以拋出任何類型的異常。

      之所以要使用finalize(),是存在着垃圾回收器不能處理的特殊情況。例如:1)由於在分配內存的時候可能採用了類似 C語言的做法,而非JAVA的通常new做法。這種情況主要發生在native method中,比如native method調用了C/C++方法malloc()函數系列來分配存儲空間,但是除非調用free()函數,否則這些內存空間將不會得到釋放,那麼這個時候就可能造成內存泄漏。但是由於free()方法是在C/C++中的函數,所以finalize()中可以用本地方法來調用它。以釋放這些“特殊”的內存空間。2)又或者打開的文件資源,這些資源不屬於垃圾回收器的回收範圍。

  2.3 減少GC開銷的措施

    1)不要顯式調用System.gc()。此函數建議JVM進行主GC,雖然只是建議而非一定,但很多情況下它會觸發主GC,從而增加主GC的頻率,也即增加了間歇性停頓的次數。大大的影響系統性能。

     2)儘量減少臨時對象的使用。臨時對象在跳出函數調用後,會成爲垃圾,少用臨時變量就相當於減少了垃圾的產生,從而延長了出現上述第二個觸發條件出現的時間,減少了主GC的機會。

    3)對象不用時最好顯式置爲Null。一般而言,爲Null的對象都會被作爲垃圾處理,所以將不用的對象顯式地設爲Null,有利於GC收集器判定垃圾,從而提高了GC的效率。

    4)儘量使用StringBuffer,而不用String來累加字符串。由於String是固定長的字符串對象,累加String對象時,並非在一個String對象中擴增,而是重新創建新的String對象,如Str5=Str1+Str2+Str3+Str4,這條語句執行過程中會產生多個垃圾對象,因爲對次作“+”操作時都必須創建新的String對象,但這些過渡對象對系統來說是沒有實際意義的,只會增加更多的垃圾。避免這種情況可以改用StringBuffer來累加字符串,因StringBuffer是可變長的,它在原有基礎上進行擴增,不會產生中間對象。

    5)能用基本類型如Int,Long,就不用Integer,Long對象。基本類型變量佔用的內存資源比相應對象佔用的少得多,如果沒有必要,最好使用基本變量。

    6)儘量少用靜態對象變量。靜態變量屬於全局變量,不會被GC回收,它們會一直佔用內存。

    7)分散對象創建或刪除的時間。集中在短時間內大量創建新對象,特別是大對象,會導致突然需要大量內存,JVM在面臨這種情況時,只能進行主GC,以回收內存或整合內存碎片,從而增加主GC的頻率。集中刪除對象,道理也是一樣的。它使得突然出現了大量的垃圾對象,空閒空間必然減少,從而大大增加了下一次創建新對象時強制主GC的機會。

  

  2.4 對象在JVM堆區的狀態

    1)可觸及狀態:程序中還有變量引用,那麼此對象爲可觸及狀態。

    2)可復活狀態:當程序中已經沒有變量引用這個對象,那麼此對象由可觸及狀態轉爲可復活狀態。CG線程將在一定的時間準備調用此對象的finalize方法(finalize方法繼承或重寫子Object),finalize方法內的代碼有可能將對象轉爲可觸及狀態,否則對象轉化爲不可觸及狀態。

    3)不可觸及狀態:只有當對象處於不可觸及狀態時,GC線程才能回收此對象的內存。

發佈了95 篇原創文章 · 獲贊 19 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章