- 相關(guān)推薦
Java 語(yǔ)言與C語(yǔ)言中垃圾回收的不同方式
導語(yǔ):垃圾回收是一種動(dòng)態(tài)存儲管理技術(shù),它自動(dòng)地釋放不再被程序引用的對象,按照特定的垃圾回收算法來(lái)實(shí)現資源自動(dòng)回收。下面就由小編為大家介紹一下Java 語(yǔ)言與C語(yǔ)言中垃圾回收的不同方式,歡迎大家閱讀!

1 Java語(yǔ)言中的垃圾回收機制
時(shí)下最流行的編程語(yǔ)言Java擁有自己的垃圾回收機制。實(shí)際上,Java語(yǔ)言來(lái)自于C++語(yǔ)言。但Java語(yǔ)言避免了C++語(yǔ)言中復雜的結構,成功克服了多重繼承機制存在的二義性問(wèn)題;Java的垃圾回收機制顯著(zhù)地提高了程序的效率,降低了復雜度。由于有垃圾回收機制,使Java中的對象不再有“作用域”的概念,而只有對象的引用才有“作用域”。垃圾回收器是一種動(dòng)態(tài)存儲分配器,它自動(dòng)釋放程序不再需要的已分配堆塊,并且能夠壓縮進(jìn)程堆塊所需要的內存空間。垃圾收集是指自動(dòng)回收不被程序占用的分配堆塊的過(guò)程。在一個(gè)支持垃圾收集的系統中,應用顯式分配堆塊,但是從不顯式釋放堆塊。垃圾回收器一般是作為一個(gè)低級別的獨立線(xiàn)程運行,不可預知的情況下對內存堆中已經(jīng)廢除的或者長(cháng)時(shí)間沒(méi)有使用的對象進(jìn)行清除和回收,而程序員不能實(shí)時(shí)的調用垃圾回收器對某個(gè)對象或所有對象進(jìn)行垃圾回收。
Java編程人員不用擔心內存管理,垃圾收集器會(huì )自動(dòng)進(jìn)行管理。但是垃圾回收機制通常只在滿(mǎn)足兩個(gè)條件時(shí)才運行:即有對象要求回收并且系統需要回收。那么,Java的垃圾回收機制是如何操作的呢?下面我們來(lái)了解一下Java垃圾回收機制的算法。
1.1 引用計數法
引用計數法,是最原始也是被很多語(yǔ)言所廣泛應用的垃圾回收算法。其主旨是給堆中每一個(gè)對象都設置一個(gè)引用計數,當其被賦值給對象的引用時(shí),其引用計數加1,當其對象的引用超出生命周期或者被新值賦值時(shí),引用減1,當其引用計數為0時(shí),即可被系統回收。
1.2 跟蹤算法
引用計數法一種重要的問(wèn)題在于當對象間出現循環(huán)引用的時(shí)候,其計數永遠不會(huì )為0,既永遠不會(huì )被回收。跟蹤算法解決了這一問(wèn)題,跟蹤算法是采用從根集開(kāi)始掃描來(lái)識別對象是否可達。標記可達的對象,將不可達的對象也就是未標記的對象清除,又稱(chēng)標記和清除算法。
1.3 壓縮算法
跟蹤算法的一個(gè)問(wèn)題就是清除對象后的內存空間變成了堆碎片,不便于再次利用。為了解決這個(gè)問(wèn)題,引入了壓縮算法。所謂壓縮算法就是在清除的過(guò)程中,將所有對象移動(dòng)到堆的一端,而本來(lái)的那端就變成了一段空閑內存區,收集器要對移動(dòng)對象的所有引用進(jìn)行更新。
1.4 復制算法
壓縮算法的問(wèn)題在于每次對對象引用更新的時(shí)候都產(chǎn)生了冗余的句柄和句柄表。為此,又引入了復制算法,復制算法的主旨是在一開(kāi)始就把堆分成一個(gè)對象面和多個(gè)空閑面,將對象面的內存空間分配給程序,當空間滿(mǎn)了的時(shí)候,利用追蹤算法的機理掃描活動(dòng)對象,但并不清除,而是將每個(gè)活動(dòng)對象復制到空閑面,這樣空閑面和對象面就互換了。
1.5 分代算法
復制算法又稱(chēng)停止和復制算法,在其對象面和空閑面切換的過(guò)程中程序要暫停執行,這樣大大降低了程序執行的效率。分代算法正好可以解決這個(gè)問(wèn)題。分代算法基于程序中大多數對象生命周期較短,少數較長(cháng)的特點(diǎn),將堆分成多個(gè),每個(gè)子堆作為對象的一代。垃圾收集器從最新創(chuàng )建的對象中,將活躍的對象移到最高代的子堆中,這樣老一代的子堆不會(huì )被經(jīng);厥,利用這種分代式的方法,節約了時(shí)間。
1.6 自適應算法
自適應法,就是指根據特殊情況,采取特殊算法,通過(guò)監控當前堆的使用情況選擇適當的算法進(jìn)行垃圾回收。
垃圾回收要占用時(shí)間,因此,Java運行時(shí),系統只在需要的時(shí)候才使用它,而編程者本身無(wú)法知道回收發(fā)生的準確時(shí)間。但如果需要垃圾回收,編程者也可以隨時(shí)調用下面的方法之一:
System.gc();
Runtime.getRuntime().gc();
2 C語(yǔ)言中的垃圾回收
C語(yǔ)言憑借其簡(jiǎn)潔緊湊、數據類(lèi)型豐富、程序執行效率高等特點(diǎn),擁有著(zhù)大量的編程愛(ài)好者,而眾多IT界牛人也說(shuō),精通C語(yǔ)言,就等于精通編程。然而C語(yǔ)言實(shí)際上是沒(méi)有垃圾回收機制的,那么被如此廣泛應用的編程語(yǔ)言如何來(lái)處理其垃圾回收問(wèn)題呢?
答案就是使用保守垃圾收集器并調用free()函數。像Java語(yǔ)言中,垃圾收集器對于指針的創(chuàng )建和使用有著(zhù)嚴格的控制,所以其能回收所有的垃圾內存,而諸如C這樣的語(yǔ)言,垃圾收集器不能被嚴格控制,則稱(chēng)之為保守垃圾收集器。
那么在C語(yǔ)言中的垃圾收集器是如何工作的呢?
C語(yǔ)言支持垃圾回收系統,如前文所說(shuō),在支持垃圾收集的系統中,應用顯示分配堆塊,但不顯式地釋放。而在C語(yǔ)言程序中,應用程序調用malloc()函數但是從不調用free()函數,取而代之的是使用垃圾收集器周期性識別垃圾堆塊,并需要編程人員調用free()函數,將這些垃圾堆塊放回到空閑鏈表中。因此,只依靠垃圾收集器是無(wú)法做到垃圾內存的全部釋放。
下面我們用有向圖的概念理解存儲器,當存在一條從任意根節點(diǎn)出發(fā)并到達Q點(diǎn)的有向路徑時(shí),我們說(shuō)節點(diǎn)Q是可達的。Java語(yǔ)言中的垃圾回收器,能夠準確的標記每個(gè)節點(diǎn)是否可達,并將不可達的節點(diǎn)回收,放入空鏈表中。而C語(yǔ)言的垃圾回收器,就是我們所說(shuō)的保守垃圾回收器,能夠正確地標記可達的節點(diǎn),但一些不可達的節點(diǎn)卻有可能被錯誤地標記為可達。從而,被錯誤標記的節點(diǎn),將永遠不會(huì )被回收?上攵,當系統中的內存被錯誤標記所占滿(mǎn)時(shí),系統將無(wú)法再運行。
下面我們來(lái)看,垃圾收集器如何為C程序將一個(gè)保守的收集器加入到已存在的malloc()函數中,如圖1所示。
垃圾收集器作為一個(gè)應用并行的獨立線(xiàn)程,不斷地更新有向圖和回收垃圾。無(wú)論應用程序何時(shí)需要內存空間,系統都會(huì )調用malloc()函數,如果malloc()函數找不到可用的內存分配快,那么它就調用垃圾收集器,垃圾收集器識別出垃圾塊,并通過(guò)調用free()函數將它們返回給堆塊。這里的關(guān)鍵在于,垃圾收集器代替了應用程序去調用free()函數,當對垃圾收集的調用返回時(shí),malloc()函數想要發(fā)現一個(gè)可用的空閑塊。如果還是不成功,它就向操作系統請求額外的存儲器。最后,如果成功,malloc()函數返回一個(gè)指向請求塊的指針,如果不成功就返回一個(gè)空指針。
3 小結
綜上所述,不同語(yǔ)言對于垃圾回收的方式不同,但是不管是什么語(yǔ)言,垃圾回收都有著(zhù)重要的作用。所以,在編程學(xué)習中,尤其是編程入門(mén)階段應該養成調用內存釋放函數的好習慣,在每次占用內存結束后,應主動(dòng)釋放內存,這樣即節省內存空間,又提高系統效率。
【Java 語(yǔ)言與C語(yǔ)言中垃圾回收的不同方式】相關(guān)文章:
在C語(yǔ)言中函數調用方式的區別09-01
C語(yǔ)言中函數之間地址傳遞方式10-23
C語(yǔ)言中的整數06-16
C語(yǔ)言中的字符07-18
java垃圾回收機制06-28
java垃圾回收算法講解08-27
JAVA語(yǔ)言中的參數傳遞11-03
C語(yǔ)言中volatile的含義08-14
c語(yǔ)言中怎么畫(huà)圖11-06