Ⅰ jvm垃圾回收演算法有哪些
1.標記–清除演算法
執行步驟:
標記:遍歷內存區域,對需要回收的對象打上標記。
清除:再次遍歷內存,對已經標記過的內存進行回收。
2.復制演算法
將內存劃分為等大的兩塊,每次只使用其中的一塊。當一塊用完了,觸發GC時,將該塊中存活的對象復制到另一塊區域,然後一次性清理掉這塊沒有用的內存。下次觸發GC時將那塊中存活的的又復制到這塊,然後抹掉那塊,循環往復。
3. 標記–整理演算法
因為前面的復制演算法當對象的存活率比較高時,這樣一直復制過來,復制過去,沒啥意義,且浪費時間。所以針對老年代提出了「標記整理」演算法。
執行步驟:
標記:對需要回收的進行標記
整理:讓存活的對象,向內存的一端移動,然後直接清理掉沒有用的內存。
4. 分代收集演算法
當前大多商用虛擬機都採用這種分代收集演算法,這個演算法並沒有新的內容,只是根據對象的存活的時間的長短,將內存分為了新生代和老年代,這樣就可以針對不同的區域,採取對應的演算法。如:
新生代,每次都有大量對象死亡,有老年代作為內存擔保,採取復制演算法。
老年代,對象存活時間長,採用標記整理,或者標記清理演算法都可。
Ⅱ java垃圾是怎麼回收的,回收演算法
Java ,C#語言與C/C++語言一個很大的區別是java與C#具有自動垃圾回收機制。C++程序員經常需要絞盡腦汁的分析哪裡出現了內存泄漏。而在java,C#中,雖然有時也會出現內存泄漏,但大部分情況下程序員不需要考慮對象或者數據何時需要被銷毀。因此程序員不會因為錯誤的釋放內存而導致程序崩潰。垃圾回收的缺點是加大了程序的負擔,有可能影響程序的性能。
1.垃圾收集器的主要功能有
(1) 定期發現那些對象不再被引用,並把這些對象占據的堆空間釋放出來。
(2) 類似於操作系統的內存管理,垃圾收集器還需要處理由於對象動態生成與銷毀產生的堆碎塊,以便更有效的利用虛擬機內存。
2.區分活動對象與垃圾的演算法
(1)引用計數法
堆中每一個對象都有一個引用計數。當新創建一個對象,或者有變數被賦值為這個對象的引用,則這個對象的引用計數加1;當一個對象的引用超過生存期或者被設置一個新的值時,這個對象的引用計數減1。當對象的引用計數變為0時,就可以被當作垃圾收集。
這種方法的好處是垃圾收集較快,適用於實時環境。缺點是這種方法無法監測出循環引用。例如對象A引用對象B,對象B也引用對象A,則這兩個對象可能無法被垃圾收集器收集。因此這種方法是垃圾收集的早期策略,現在很少使用。
(2)跟蹤法
這種方法把每個對象看作圖中一個節點,對象之間的引用關系為圖中各節點的鄰接關系。垃圾收集器從一個或數個根結點遍歷對象圖,如果有些對象節點永遠無法到達,則這個對象可以被當作垃圾回收。
容易發現,這種方法可以檢測出循環引用,避免了引用計數法的缺點,較為常用。
3.常用垃圾回收機制
(1)標記-清除收集器
這種收集器首先遍歷對象圖並標記可到達的對象,然後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器一般使用單線程工作並停止其他操作。
(2)標記-壓縮收集器
有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象復制到堆棧的新域中以便壓縮堆棧。這種收集器也停止其他操作。
(3)復制收集器
這種收集器將堆棧分為兩個域,常稱為半空間。每次僅使用一半的空間,虛擬機生成的新對象則放在另一半空間中。垃圾回收器運行時,它把可到達對象復制到另一半空間,沒有被復制的的對象都是不可達對象,可以被回收。這種方法適用於短生存期的對象,持續復制長生存期的對象由於多次拷貝,導致效率降低。缺點是只有一半的虛擬機空間得到使用。
(4)增量收集器
增量收集器把堆棧分為多個域,每次僅從一個域收集垃圾。這會造成較小的應用程序中斷。
(5)分代收集器
這種收集器把堆棧分為兩個或多個域,用以存放不同壽命的對象。虛擬機生成的新對象一般放在其中的某個域中。過一段時間,繼續存在的對象將獲得使用期並轉入更長壽命的域中。分代收集器對不同的域使用不同的演算法以優化性能。這樣可以減少復制對象的時間。
(6)並發收集器
並發收集器與應用程序同時運行。這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務,但是因為其他應用程序可進行其他的後台操作,所以中斷其他處理的實際時間大大降低。
(7)並行收集器
並行收集器使用某種傳統的演算法並使用多線程並行的執行它們的工作。在多CPU機器上使用多線程技術可以顯著的提高java應用程序的可擴展性。
(8)自適應收集器
根據程序運行狀況以及堆的使用狀況,自動選一種合適的垃圾回收演算法。這樣可以不局限與一種垃圾回收演算法。
4. 火車演算法
垃圾收集演算法一個很大的缺點就是難以控制垃圾回收所佔用的CPU時間,以及何時需要進行垃圾回收。火車演算法是分代收集器所用的演算法,目的是在成熟對象空間中提供限定時間的漸進收集。目前應用於SUN公司的Hotspot虛擬機上。
在火車演算法中,內存被分為塊,多個塊組成一個集合。為了形象化,一節車廂代表一個塊,一列火車代表一個集合,見圖一
注意每個車廂大小相等,但每個火車包含的車廂數不一定相等。垃圾收集以車廂為單位,收集順序依次為1.1,1.2,1.3,1.4,2.1,2.2,2.3,3.1,3.2,3.3。這個順序也是塊被創建的先後順序。
垃圾收集器先從塊1.1開始掃描直到1.4,如果火車1四個塊中的所有對象沒有被火車2和火車3的對象引用,而只有火車1內部的對象相互引用,則整個火車1都是垃圾,可以被回收。
如圖二,車廂1.1中有對象A和對象B,1.3中有對象C,1.4中有對象D,車廂2.2中有對象E,車廂3.3中有對象F。在火車1中,對象C引用對象A,對象B引用對象D,可見,火車2和火車3沒有引用火車1的對象,則整個火車1都是垃圾。
如果火車1中有對象被其它火車引用,見圖三,掃描車廂1.1時發現對象A被火車2中的E引用,則將對象A從車廂1.1轉移到車廂2.2,然後掃描A引用的對象D,把D也轉移到車廂2.2,然後掃描D,看D是否引用其它對象,如果引用了其它對象則也要轉移,依次類推。掃描完火車1的所有對象後,剩下的沒有轉移的對象都是垃圾,可以把整個火車1都作為垃圾回收。注意如果在轉移時,如果車廂2.2空間滿了,則要在火車2末尾開辟新的車廂2.4,將新轉移的對象都放到2.4,即火車的尾部)
補充說明:垃圾回收器一次只掃描一個車廂。圖三中的對象B與C並不是立即被回收,而是先會被轉移到火車1的尾部車廂。即掃描完1.1後,B被轉移到火車1尾部,掃描完1.3後,C被轉移到車尾。等垃圾收集器掃描到火車1尾部時,如果仍然沒有外部對象引用它們,則B和C會被收集。
火車演算法最大的好處是它可以保證大的循環結構可以被完全收集,因為成為垃圾的循環結構中的對象,無論多大,都會被移入同一列火車,最終一起被收集。還有一個好處是這種演算法在大多數情況下可以保證一次垃圾收集所耗時間在一定限度之內,因為一次垃圾回收只收集一個車廂,而車廂的大小是有限度的。
Ⅲ 舉例說明一個典型的垃圾回收演算法
關於java里的垃圾回收演算法,初學者經常產生的疑問是,像這樣的代碼里的無用單元:
class Test{
public Test test = null;
public static void main(String args[]){
Test t1 = new Test();
Test t2 = new Test();
t1.test=t2;
t2.test=t1;
t1=null;
t2=null;
}
}
java能不能自動回收?
java是可以回收的.對此有疑問的人的想法是以為java是採用引用計數法實現垃圾回收的.實際上,java不是用此方法,所以可以回收.
1:引用計數,如下,當單元count=0時回收此單元
Test t1 = new Test();//t1指向單元count=1
Test t2 = new Test();//t2指向單元count=1
t1.test=t2;//t2指向單元count++,count=2
t2.test=t1;//t2指向單元count++,count=2
t1=null;//t1指向單元count--,count=1
t2=null;//t2指向單元count--,count=1
兩單元均不可達,為無用單元,但引用計數count=1,!=0,不能回收.
2:java的演算法(簡化)
基本思想:為了避免懸掛引用,寧可產生無用單元,只在空間用完,需要新單元時才進行垃圾回收.
過程:
1:標記Mark
首先,所有單元標記為off,然後,java所有thread的棧stack內引用的單元標記為on,對所有標記為on的單元引用的其他單元標記為on.
2:掃描Sweep
掃描堆heap,所有標記為off的單元一概回收.
所以,上述程序中無用單元是可以回收的.
Ⅳ java虛擬機常見的幾種垃圾收集演算法
1、垃圾收集器概述
垃圾收集器是垃圾回收演算法(標記-清除演算法、復制演算法、標記-整理演算法、火車演算法)的具體實現,不同商家、不同版本的JVM所提供的垃圾收集器可能會有很在差別,本文主要介紹HotSpot虛擬機中的垃圾收集器。
1-1、垃圾收集器組合
JDK7/8後,HotSpot虛擬機所有收集器及組合(連線),如下圖:
(A)、圖中展示了7種不同分代的收集器:
Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;
(B)、而它們所處區域,則表明其是屬於新生代收集器還是老年代收集器:
新生代收集器:Serial、ParNew、Parallel Scavenge;
老年代收集器:Serial Old、Parallel Old、CMS;
整堆收集器:G1;
(C)、兩個收集器間有連線,表明它們可以搭配使用:
Serial/Serial Old、Serial/CMS、ParNew/Serial Old、ParNew/CMS、Parallel Scavenge/Serial Old、Parallel Scavenge/Parallel Old、G1;
(D)、其中Serial Old作為CMS出現"Concurrent Mode Failure"失敗的後備預案(後面介紹);
1-2、並發垃圾收集和並行垃圾收集的區別
(A)、並行(Parallel)
指多條垃圾收集線程並行工作,但此時用戶線程仍然處於等待狀態;
如ParNew、Parallel Scavenge、Parallel Old;
(B)、並發(Concurrent)
指用戶線程與垃圾收集線程同時執行(但不一定是並行的,可能會交替執行);
用戶程序在繼續運行,而垃圾收集程序線程運行於另一個CPU上;
如CMS、G1(也有並行);
1-3、Minor GC和Full GC的區別
(A)、Minor GC
又稱新生代GC,指發生在新生代的垃圾收集動作;
因為Java對象大多是朝生夕滅,所以Minor GC非常頻繁,一般回收速度也比較快;
(B)、Full GC
又稱Major GC或老年代GC,指發生在老年代的GC;
出現Full GC經常會伴隨至少一次的Minor GC(不是絕對,Parallel Sacvenge收集器就可以選擇設置Major GC策略);
Major GC速度一般比Minor GC慢10倍以上;
Ⅳ JVM有哪些垃圾回收演算法
標記-清除,標記-復制,標記-整理
Ⅵ 現在android上的Dalvik是用哪個垃圾回收演算法
Dalvik虛擬機使用Mark-Sweep演算法來進行垃圾收集。顧名思義,Mark-Sweep演算法就是為Mark和Sweep兩個階段進行垃圾回收。其中,Mark階段從根集(Root Set)開始,遞歸地標記出當前所有被引用的對象,而Sweep階段負責回收那些沒有被引用的對象。
Ⅶ JVM的垃圾演算法有哪幾種
一、垃圾收集器概述
如上圖所示,垃圾回收演算法一共有7個,3個屬於年輕代、三個屬於年老代,G1屬於橫跨年輕代和年老代的演算法。
JVM會從年輕代和年老代各選出一個演算法進行組合,連線表示哪些演算法可以組合使用
二、各個垃圾收集器說明
1、Serial(年輕代)
年輕代收集器,可以和Serial Old、CMS組合使用
採用復制演算法
使用單線程進行垃圾回收,回收時會導致Stop The World,用戶進程停止
client模式年輕代默認演算法
GC日誌關鍵字:DefNew(Default New Generation)
圖示(Serial+Serial Old)
7、G1
G1收集器由於沒有使用過,所以從網上找了一些教程供大家了解
並行與並發
分代收集
空間整合
可預測的停頓
Ⅷ java垃圾回收機制
由於使用new運算符來為對象動態地分配內存,你可能想知道這些對象是如何撤消的
以及他們的內存在以後的重新分配時是如何被釋放的。在一些語言,例如C++中,用delete
運算符來手工地釋放動態分配的對象的內存。Java使用一種不同的、自動地處理重新分配
內存的辦法:垃圾回收( garbage collection)技術,它是這樣工作的:當一個對象的引用不存
在時,則該對象被認為是不再需要的,它所佔用的內存就被釋放掉。它不像C++那樣需要
顯式撤消對象。垃圾回收只在你的程序執行過程中偶爾發生。它不會因為一個或幾個存在
的對象不再被使用而發生。況且,Java不同的運行時刻會產生各種不同的垃圾回收辦法,
但是對你編寫的大多數程序,你不必須考慮垃圾回收問題。
Ⅸ jvm垃圾回收是什麼時候觸發的垃圾回收演算法
1.垃圾回收目的:Java語言中一個顯著的特點就是引入了垃圾回收機制,使c++程序員最頭疼的內存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內存管理。由於有個垃圾回收機制,Java中的對象不再有「作用域」的概念,只有對象的引用才有「作用域」。垃圾回收可以有效的防止內存泄露,有效的使用空閑的內存。
ps:內存泄露是指該內存空間使用完畢之後未回收,在不涉及復雜數據結構的一般情況下,Java 的內存泄露表現為一個內存對象的生命周期超出了程序需要它的時間長度,我們有時也將其稱為「對象游離」。
2.
由於對象進行了分代處理,因此垃圾回收區域、時間也不一樣。GC有兩種類型:Scavenge GC和Full GC。
Scavenge GC
一般情況下,當新對象生成,並且在Eden申請空間失敗時,就會觸發Scavenge GC,對Eden區域進行GC,清除非存活對象,並且把尚且存活的對象移動到Survivor區。然後整理Survivor的兩個區。這種方式的GC是對年輕代的Eden區進行,不會影響到年老代。因為大部分對象都是從Eden區開始的,同時Eden區不會分配的很大,所以Eden區的GC會頻繁進行。因而,一般在這里需要使用速度快、效率高的演算法,使Eden去能盡快空閑出來。
Full GC
對整個堆進行整理,包括Young、Tenured和Perm。Full GC因為需要對整個堆進行回收,所以比Scavenge GC要慢,因此應該盡可能減少Full GC的次數。在對JVM調優的過程中,很大一部分工作就是對於FullGC的調節。有如下原因可能導致Full GC:
1.年老代(Tenured)被寫滿
2.持久代(Perm)被寫滿
3.System.gc()被顯示調用
4.上一次GC之後Heap的各域分配策略動態變化
Ⅹ 各種編程語言的實現都採用了哪些垃圾回收演算法
java語言: . 採用Reference Counting的垃圾回收器 對於採用Reference Counting的垃圾回收器,系統為堆上每一個對象都維護一個計數器,當一個對象被創建並且別引用時,這個計數就被置為1。當有新的變數引用該對象,計數器進行自加運算。當一個引用超出作用范圍或者被賦予新值的時候,計數器進行自減運算。引用計數為0的對象,會被作為垃圾回收。當一個對象被回收,該對象所引用的對象的引用計數都會相應減少,因而,一個對象的回收有時會引起其它對象的回收。 Reference Counting方式的垃圾回收器,好處在於可以在很短的時間內運行,不會長時間的中斷普通的程序運行,因而在RealTime的系統中應用較為普遍。 Reference Counting方式的垃圾回收器,問題在於無法識別循環引用,比如父類對象還有子類引用的情況,即便父類和子類都已經不再能被訪問到(unreachable),引用計數也把它們清除。另外一個問題是引用計數器的加減運算會增加系統的計算開銷。 2. 採用Tracing的垃圾回收器 採用Tracing的垃圾回收器,遍歷由根節點(root nodes)出發的引用關系圖。在遍歷過程中遇到的對象,就被標記為活動。標記既可以是對應對象中的某一個標志,也可以是獨立的點陣圖中的標志。當遍歷完成以後,那些沒有被標記的對象,就被作為垃圾回收了。最基本Tracing演算法是"Mark and Sweep" 垃圾回收器的另外一個責任是清除堆上的碎片(Fragmentation)。對於Mark and Sweep的垃圾回收器通常有兩種實現方法來減少堆上的碎片: 壓縮(Compacting)和拷貝(Copying) 在編程語言Python中,使用也是引用計數演算法。 節點拷貝演算法 節點拷貝演算法是把整個堆分成兩個半區(From,To), GC的過程其實就是把存活對象從一個半區From拷貝到另外一個半區To的過程,而在下一次回收時,兩個半區再互換角色。在移動結束後,再更新對象的指針引用。