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

jvm學習筆記一(垃圾回收算法),jvm學習筆記

編輯:JAVA綜合教程

jvm學習筆記一(垃圾回收算法),jvm學習筆記


一:垃圾回收機制的原因

  java中,當沒有對象引用指向原先分配給某個對象的內存時候,該內存就成為了垃圾。JVM的一個系統級線程會自動釋放該內存塊。垃圾回收意味著程序不再需要的對象是"無用信息",這些信息將被丟棄。當一個對象不再被引用的時候,內存回收它占領的空間,以便空間被後來的新對象使用。事實上,除了釋放沒用的對象,垃圾回收也可以清除內存記錄碎片。由於創建對象和垃圾回收器釋放丟棄對象所占的內存空間,內存會出現碎片。碎片是分配給對象的內存塊之間的空閒內存洞。碎片整理將所占用的堆內存移到堆的一端,JVM將整理出的內存分配給新的對象。

  垃圾回收的優點:垃圾回收能自動釋放內存空間,減輕編程的負擔。首先,它能使編程效率提高。在沒有垃圾回收機制的時候,可能要花許多時間來解決一個難懂的存儲器問題。在用Java語言編程的時候,靠垃圾回收機制可大大縮短時間。其次是它保護程序的完整性, 垃圾回收是Java語言安全性策略的一個重要部份。

  垃圾回收的缺點:垃圾回收的開銷影響程序性能。Java虛擬機必須追蹤運行程序中有用的對象,而且最終釋放沒用的對象。這一個過程需要花費處理器的時間。其次垃圾回收算法的不完備性,早先采用的某些垃圾回收算法就不能保證100%收集到所有的廢棄內存。當然隨著垃圾回收算法的不斷改進以及軟硬件運行效率的不斷提升,這些問題都可以迎刃而解。

二:垃圾收集的算法分析

  1.引用計數器算法:

  引用計數法是唯一沒有使用根集的垃圾回收的方法,該算法使用引用計數器來區分存活對象和不再使用的對象。

  引用計數器算法是給每個對象設置一個計數器,當有地方引用這個對象的時候,計數器+1,當引用失效的時候,計數器-1,當計數器為0的時候,JVM就認為對象不再被使用,是“垃圾”了。

引用計數器實現簡單,效率高;但是不能解決循環引用問問題(A對象引用B對象,B對象又引用A對象,但是A,B對象已不被任何其他對象引用),同時每次計數器的增加和減少都帶來了很多額外的開銷,所以在JDK1.1之後,這個算法已經不再使用了。

  2.根搜索方法:

  大多數垃圾回收算法使用了根集(root set)這個概念;所謂根集就是正在執行的Java程序可以訪問的引用變量的集合(包括局部變量、參數、類變量),程序可以使用引用變量訪問對象的屬性和調用對象的方法。垃圾回收首先需要確定從根開始哪些是可達的和哪些是不可達的,從根集可達的對象都是活動對象,它們不能作為垃圾被回收,這也包括從根集間接可達的對象。而根集通過任意路徑不可達的對象符合垃圾收集的條件,應該被回收。下面介紹幾個常用的算法。

  2.1 標記—清除算法(Mark-Sweep)

  原理:標記—清除算法包括兩個階段:“標記”和“清除”。在標記階段,確定所有要回收的對象,並做標記。清除階段緊隨標記階段,將標記階段確定不可用的對象清除。

 

  缺點:標記—清除算法是基礎的收集算法,標記和清除階段的效率不高,而且清除後回產生大量的不連續空間,這樣當程序需要分配大內存對象時,可能無法找到足夠的連續空間。

  垃圾回收前:

 

      

 

  垃圾回收後:

 

      

 

  綠色:存活對象 紅色:可回收對象 白色:未使用空間

  2.2復制算法(Copying)

  原理:復制算法是把內存分成大小相等的兩塊,每次使用其中一塊,當垃圾回收的時候,把存活的對象復制到另一塊上,然後把這塊內存整個清理掉。

  缺點:復制算法實現簡單,運行效率高,但是由於每次只能使用其中的一半,造成內存的利用率不高。現在的JVM用復制方法收集新生代,由於新生代中大部分對象(98%)都是朝生夕死的,所以兩塊內存的比例不是1:1(大概是8:1)。

 

  垃圾回收前:

      

 

  垃圾回收後:

 

       

 

    綠色:存活對象 紅色:可回收對象 白色:未使用空間

  2.3 標記—整理算法(Mark-Compact)

  原理:標記—整理算法和標記—清除算法一樣,但是標記—整理算法不是把存活對象復制到另一塊內存,而是把存活對象往內存的一端移動,然後直接回收邊界以外的內存。

  標記—整理算法提高了內存的利用率,並且它適合在收集對象存活時間較長的老年代。

  垃圾回收前:

      

  垃圾回收後:

      

      綠色:存活對象 紅色:可回收對象 白色:未使用空間

  上面這四種是最基本的垃圾回收算法,在這四種算法思想之上發展出來其余算法,個人認為更多的是一種內存管理策略,甚至可以看成就是基本算法的組合應用,就像加減乘除與方程式的關系一樣,因此將其分開描述。

 

  3.漸進式算法

    這類算法一般由基本算法組成,其核心思想是將內存分區域進行管理,在不同的區域和不同的時間采用不同的內存管理策略,從而避免因全系統的垃圾回收導致程序長時間暫停。這類算法一般有以下幾種:

   3.1.火車算法

    這種算法把成熟的內存空間劃為固定長度的內存塊,算法每次在一個塊中單獨執行,每一個塊屬於一個集合。此算法的具體執行步驟較復雜,且沒有具體的應用場景,在此不浪費筆墨,有興趣的同學可以自己研究之。

    3.2.分代收集算法

    這種算法在sun/oracle公司的Hotspot虛擬機中得到應用,是java程序員需要重點關注的一種算法。

    這種算法是通過對對象的生命周期進行分析後得出的,它將堆內存分成了三個部分:年青代,年老代,持久代(相當於方法區)。處於不同生命周期的對象被存儲於不同的區域,並使用不同的算法進行回收。這種算法的具體執行細節將會在後續的學習筆記中詳細介紹。

  關於分代收集 詳見 http://www.importnew.com/19255.html

    另外需要特別注意的是利用多線程實現的堆垃圾回收技術,這方面資料來源於網絡,摘抄如下:

 4.多線程實現的堆垃圾回收技術

    4.1.串行收集

    串行收集使用單線程處理所有垃圾回收工作,因為無需多線程交互,實現容易,而且效率比較高。但是,其局限性也比較明顯,即無法使用多處理器的優勢,所以此收集適合單處理器機器。當然,此收集器也可以用在小數據量(100M左右)情況下的多處理器機器上。

    適用情況:數據量比較小(100M左右);單處理器下並且對響應時間無要求的應用。

    缺點:只能用於小型應用。

    4.2.並行收集

    並行收集使用多線程處理垃圾回收工作,因而速度快,效率高。而且理論上CPU數目越多,越能體現出並行收集器的優勢。

    適用情況:“對吞吐量有高要求”,多CPU、對應用響應時間無要求的中、大型應用。舉例:後台處理、科學計算。

    缺點:應用響應時間可能較長 。

    4.3.並發收集

    相對於串行收集和並行收集而言,前面兩個在進行垃圾回收工作時,需要暫停整個運行環境,而只有垃圾回收程序在運行,因此,系統在垃圾回收時會有明顯的暫停,而且暫停時間會因為堆越大而越長。

    適用情況:“對響應時間有高要求”,多CPU、對應用響應時間有較高要求的中、大型應用。舉例:Web服務器/應用服務器、電信交換、集成開發環境。

 

參考:

http://blog.csdn.net/zsuguangh/article/details/6429592

http://blog.csdn.net/ol_beta/article/details/6791229

https://my.oschina.net/GameKing/blog/198347

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