熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

Java的垃圾收集機制

2013-11-15 11:40:16  來源: JSP教程 

  通常我們把分配出去後卻無法回收的內存空間稱為內存滲漏體(Memory Leaks)
  
  以上這種程序設計的潛在危險性在Java這樣以嚴謹安全著稱的語言中是不允許的但是Java語言既不能限制程序員編寫程序的自由性又不能把聲明對象的部分去除(否則就不是面向對象的程序語言了)那麼最好的解決辦法就是從Java程序語言本身的特性入手於是Java技術提供了一個系統級的線程(Thread)即垃圾收集器線程(Garbage Collection Thread)來跟蹤每一塊分配出去的內存空間當Java 虛擬機(Java Virtual Machine)處於空閒循環時垃圾收集器線程會自動檢查每一快分配出去的內存空間然後自動回收每一快可以回收的無用的內存塊
  
  垃圾收集器線程是一種低優先級的線程在一個Java程序的生命周期中它只有在內存空閒的時候才有機會運行它有效地防止了內存滲漏體的出現並極大可能地節省了寶貴的內存資源但是通過Java虛擬機來執行垃圾收集器的方案可以是多種多樣的
  
  下面介紹垃圾收集器的特點和它的執行機制
  
  垃圾收集器系統有自己的一套方案來判斷哪個內存塊是應該被回收的哪個是不符合要求暫不回收的垃圾收集器在一個Java程序中的執行是自動的不能強制執行即使程序員能明確地判斷出有一塊內存已經無用了是應該回收的程序員也不能強制垃圾收集器回收該內存塊程序員唯一能做的就是通過調用System gc 方法來建議執行垃圾收集器但其是否可以執行什麼時候執行卻都是不可知的這也是垃圾收集器的最主要的缺點當然相對於它給程序員帶來的巨大方便性而言這個缺點是瑕不掩瑜的
  
  垃圾收集器的主要特點
  .垃圾收集器的工作目標是回收已經無用的對象的內存空間從而避免內存滲漏體的產生節省內存資源避免程序代碼的崩潰
  .垃圾收集器判斷一個對象的內存空間是否無用的標准是如果該對象不能再被程序中任何一個活動的部分所引用此時我們就說該對象的內存空間已經無用所謂活動的部分是指程序中某部分參與程序的調用正在執行過程中尚未執行完畢
  .垃圾收集器線程雖然是作為低優先級的線程運行但在系統可用內存量過低的時候它可能會突發地執行來挽救內存資源當然其執行與否也是不可預知的
  .垃圾收集器不可以被強制執行但程序員可以通過調用System gc方法來建議執行垃圾收集器
  .不能保證一個無用的對象一定會被垃圾收集器收集也不能保證垃圾收集器在一段Java語言代碼中一定會執行因此在程序執行過程中被分配出去的內存空間可能會一直保留到該程序執行完畢除非該空間被重新分配或被其他方法回收由此可見完全徹底地根絕內存滲漏體的產生也是不可能的但是請不要忘記Java的垃圾收集器畢竟使程序員從手工回收內存空間的繁重工作中解脫了出來設想一個程序員要用C或C++來編寫一段萬行語句的代碼那麼他一定會充分體會到Java的垃圾收集器的優點!
  .同樣沒有辦法預知在一組均符合垃圾收集器收集標准的對象中哪一個會被首先收集
  .循環引用對象不會影響其被垃圾收集器收集
  .可以通過將對象的引用變量(reference variables即句柄handles)初始化為null值來暗示垃圾收集器來收集該對象但此時如果該對象連接有事件監聽器(典型的 AWT組件)那它還是不可以被收集所以在設一個引用變量為null值之前應注意該引用變量指向的對象是否被監聽若有要首先除去監聽器然後才可以賦空值
  .每一個對象都有一個finalize( )方法這個方法是從Object類繼承來的
  .finalize( )方法用來回收內存以外的系統資源就像是文件處理器和網絡連接器該方法的調用順序和用來調用該方法的對象的創建順序是無關的換句話說書寫程序時該方法的順序和方法的實際調用順序是不相干的請注意這只是finalize( )方法的特點
  .每個對象只能調用finalize( )方法一次如果在finalize( )方法執行時產生異常(exception)則該對象仍可以被垃圾收集器收集
  .垃圾收集器跟蹤每一個對象收集那些不可到達的對象(即該對象沒有被程序的任何活的部分所調用)回收其占有的內存空間但在進行垃圾收集的時候垃圾收集器會調用finalize( )方法通過讓其他對象知道它的存在而使不可到達的對象再次復蘇為可到達的對象既然每個對象只能調用一次finalize( )方法所以每個對象也只可能復蘇一次
  .finalize( )方法可以明確地被調用但它卻不能進行垃圾收集
  .finalize( )方法可以被重載(overload)但只有具備初始的finalize( )方法特點的方法才可以被垃圾收集器調用
  .子類的finalize( )方法可以明確地調用父類的finalize( )方法作為該子類對象的最後一次適當的操作但Java編譯器卻不認為這是一次覆蓋操作(overriding)所以也不會對其調用進行檢查
  .當finalize( )方法尚未被調用時System runFinalization( )方法可以用來調用finalize( )方法並實現相同的效果對無用對象進行垃圾收集
  .當一個方法執行完畢其中的局部變量就會超出使用范圍此時可以被當作垃圾收集但以後每當該方法再次被調用時其中的局部變量便會被重新創建
  .Java語言使用了一種標記交換區的垃圾收集算法該算法會遍歷程序中每一個對象的句柄為被引用的對象做標記然後回收尚未做標記的對象所謂遍歷可以簡單地理解為檢查每一個
  .Java語言允許程序員為任何方法添加finalize( )方法該方法會在垃圾收集器交換回收對象之前被調用但不要過分依賴該方法對系統資源進行回收和再利用因為該方法調用後的執行結果是不可預知的
  通過以上對垃圾收集器特點的了解你應該可以明確垃圾收集器的作用和垃圾收集器判斷一塊內存空間是否無用的標准簡單地說當你為一個對象賦值為null並且重新定向了該對象的引用者此時該對象就符合垃圾收集器的收集標准
  判斷一個對象是否符合垃圾收集器的收集標准這是SUN公司程序員認證考試中垃圾收集器部分的重要考點(可以說這是唯一的考點)所以考生在一段給定的代碼中應該能夠判斷出哪個對象符合垃圾收集器收集的標准哪個不符合下面結合幾種認證考試中可能出現的題型來具體講解
  Object obj = new Object ( ) ;
  我們知道obj為Object的一個句柄當出現new關鍵字時就給新建的對象分配內存空間而obj的值就是新分配的內存空間的首地址即該對象的值(請特別注意對象的值和對象的內容是不同含義的兩個概念對象的值就是指其內存塊的首地址即對象的句柄而對象的內容則是其具體的內存塊)此時如果有 obj = null 則obj指向的內存塊此時就無用了因為下面再沒有調用該變量了
  
  請再看以下三種認證考試時可能出現的題型
  程序段
  .fobj = new Object ( ) ;
  .fobj Method ( ) ;
  .fobj = new Object ( ) ;
  .fobj Method ( ) ;
  
  問這段代碼中fobj在第幾行符合垃圾收集器的收集標准?
  答因為第行的fobj被賦了新值產生了一個新的對象即換了一塊新的內存空間也相當於為第行中的fobj賦了null值這種類型的題在認證考試中是最簡單的
  
  程序段
  .Object sobj = new Object ( ) ;
  .Object sobj = null ;
  .Object sobj = new Object ( ) ;
  .sobj = new Object ( ) ;
  
  問這段代碼中第幾行的內存空間符合垃圾收集器的收集標准?
  答行和第因為第行為sobj賦值為null所以在此第行的sobj符合垃圾收集器的收集標准而第行相當於為sobj賦值為null所以在此第行的sobj也符合垃圾收集器的收集標准
  如果有一個對象的句柄a且你把a作為某個構造器的參數即 new Constructor ( a )的時候即使你給a賦值為nulla也不符合垃圾收集器的收集標准直到由上面構造器構造的新對象被賦空值時a才可以被垃圾收集器收集
  程序段
  .Object aobj = new Object ( ) ;
  .Object bobj = new Object ( ) ;
  .Object cobj = new Object ( ) ;
  .aobj = bobj;
  .aobj = cobj;
  .cobj = null;
  .aobj = null;
  問這段代碼中第幾行的內存空間符合垃圾收集器的收集標准?
  答注意這類題型是認證考試中可能遇到的最難題型了
  行分別創建了Object類的三個對象aobjbobjcobj
  行此時對象aobj的句柄指向bobj所以該行的執行不能使aobj符合垃圾收集器的收集標准
  行此時對象aobj的句柄指向cobj所以該行的執行不能使aobj符合垃圾收集器的收集標准
  行此時仍沒有任何一個對象符合垃圾收集器的收集標准
  行對象cobj符合了垃圾收集器的收集標准因為cobj的句柄指向單一的地址空間在第行的時候cobj已經被賦值為null但由cobj同時還指向了aobj(第行)所以此時cobj並不符合垃圾收集器的收集標准而在第aobj所指向的地址空間也被賦予了空值null這就說明了由cobj所指向的地址空間已經被完全地賦予了空值所以此時cobj最終符合了垃圾收集器的收集標准 但對於aobj和bobj仍然無法判斷其是否符合收集標准
  
  總結
  在Java語言中判斷一塊內存空間是否符合垃圾收集器收集標准的標准只有兩個
  .給對象
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19411.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.