1. 程式人生 > >Java中的垃圾回收機制的代碼

Java中的垃圾回收機制的代碼

臨時變量 我們 sage 定時 p s 告訴 說明 垃圾收集 方法

內容閑暇時間,把開發過程重要的一些內容段做個備份,下面的內容段是關於Java中的垃圾回收機制的內容,希望能對小夥伴們有用。


  class Chair {
  static boolean gcrun = false;
  static boolean f = false;
  static int created = 0;
  static int finalized = 0;
  int i;
  Chair() {
  i = ++created;
  if(created == 47)
  System.out.println("Created 47");
  }
  protected void finalize() {
  if(!gcrun) {
  gcrun = true;
  System.out.println(
  "Beginning to finalize after " +
  created + " Chairs have been created");
  }
  if(i == 47) {
  System.out.println(
  "Finalizing Chair #47, " +
  "Setting flag to stop Chair creation");
  f = true;
  }
  finalized++;
  if(finalized >= created)
  System.out.println(
  "All " + finalized + " finalized");
  }
  }
  public class Garbage {
  public static void main(String[] args) {
  if(args.length == 0) {
  System.err.println("Usage: n" +
  "java Garbage beforen or:n" +
  "java Garbage after");
  return;
  }
  while(!Chair.f) {
  new Chair();
  new String("To take up space");
  }
  System.out.println(
  "After all Chairs have been created:n" +
  "total created = " + Chair.created +
  ", total finalized = " + Chair.finalized);
  if(args[0].equals("before")) {
  System.out.println("gc():");
  System.gc();
  System.out.println("runFinalization():");
  System.runFinalization();
  }
  System.out.println("bye!");
  if(args[0].equals("after"))
  System.runFinalizersOnExit(true);
  }
  }




    上面這個程序創建了許多Chair對象,而且在垃圾收集器開始運行後的某些時候,程序會停止創建Chair。由於垃圾收集器可能在任何時間運行,所以我們不能準確知道它在何時啟動。因此,程序用一個名為gcrun的標記來指出垃圾收集器是否已經開始運行。利用第二個標記f,Chair可告訴main()它應停止對象的生成。這兩個標記都是在finalize()內部設置的,它調用於垃圾收集期間。另兩個static變量--created以及finalized--分別用於跟蹤已創建的對象數量以及垃圾收集器已進行完收尾工作的對象數量。最後,每個Chair都有它自己的(非static)inti,所以能跟蹤了解它具體的編號是多少。編號為47的Chair進行完收尾工作後,標記會設為true,最終結束Chair對象的創建過程。(關於這個例子的更具體的分析和說明請參看《Java編程思想》的第四章)    5關於垃圾收集的幾點補充    經過上述的說明,可以發現垃圾回收有以下的幾個特點:    (1)垃圾收集發生的不可預知性:由於實現了不同的垃圾收集算法和采用了不同的收集機制,所以它有可能是定時發生,有可能是當出現系統空閑CPU資源時發生,也有可能是和原始的垃圾收集一樣,等到內存消耗出現極限時發生,這與垃圾收集器的選擇和具體的設置都有關系。    (2)垃圾收集的精確性:主要包括2個方面:(a)垃圾收集器能夠精確標記活著的對象;(b)垃圾收集器能夠精確地定位對象之間的引用關系。前者是完全地回收所有廢棄對象的前提,否則就可能造成內存泄漏。而後者則是實現歸並和復制等算法的必要條件。所有不可達對象都能夠可靠地得到回收,所有對象都能夠重新分配,允許對象的復制和對象內存的縮並,這樣就有效地防止內存的支離破碎。    (3)現在有許多種不同的垃圾收集器,每種有其算法且其表現各異,既有當垃圾收集開始時就停止應用程序的運行,又有當垃圾收集開始時也允許應用程序的線程運行,還有在同一時間垃圾收集多線程運行。    (4)垃圾收集的實現和具體的JVM以及JVM的內存模型有非常緊密的關系。不同的JVM可能采用不同的垃圾收集,而JVM的內存模型決定著該JVM可以采用哪些類型垃圾收集。現在,HotSpot系列JVM中的內存系統都采用先進的面向對象的框架設計,這使得該系列JVM都可以采用最先進的垃圾收集。    (5)隨著技術的發展,現代垃圾收集技術提供許多可選的垃圾收集器,而且在配置每種收集器的時候又可以設置不同的參數,這就使得根據不同的應用環境獲得最優的應用性能成為可能。    針對以上特點,我們在使用的時候要註意:    (1)不要試圖去假定垃圾收集發生的時間,這一切都是未知的。比如,方法中的一個臨時對象在方法調用完畢後就變成了無用對象,這個時候它的內存就可以被釋放。    (2)Java中提供了一些和垃圾收集打交道的類,而且提供了一種強行執行垃圾收集的方法--調用System.gc(),但這同樣是個不確定的方法。Java中並不保證每次調用該方法就一定能夠啟動垃圾收集,它只不過會向JVM發出這樣一個申請,到底是否真正執行垃圾收集,一切都是個未知數。    (3)挑選適合自己的垃圾收集器。一般來說,如果系統沒有特殊和苛刻的性能要求,可以采用JVM的缺省選項。否則可以考慮使用有針對性的垃圾收集器,比如增量收集器就比較適合實時性要求較高的系統之中。系統具有較高的配置,有比較多的閑置資源,可以考慮使用並行標記/清除收集器。    (4)關鍵的也是難把握的問題是內存泄漏。良好的編程習慣和嚴謹的編程態度永遠是最重要的,不要讓自己的一個小錯誤導致內存出現大漏洞。    (5)盡早釋放無用對象的引用。大多數程序員在使用臨時變量的時候,都是讓引用變量在退出活動域(scope)後,自動設置為null,暗示垃圾收集器來收集該對象,還必須註意該引用的對象是否被監聽,如果有,則要去掉監聽器,然後再賦空值。    6結束語    一般來說,Java開發人員可以不重視JVM中堆內存的分配和垃圾處理收集,但是,充分理解Java的這一特性可以讓我們更有效地利用資源。同時要註意finalize()方法是Java的缺省機制,有時為確保對象資源的明確釋放,可以編寫自己的finalize方法。





Java中的垃圾回收機制的代碼