什么是GC?

時間:2024-01-04 09:55:57 閱讀:6

什么是GC?

問:什么是GC?

答: 在Java言語中,渣滓吸收(Garbage Collection,GC)是一個十分緊張的看法,它的主要作用是吸收步驟中不再使用的內存。

在使用C/C++言語舉行步驟開發時,開發職員必需十分仔細腸辦理好內存的分派與開釋,假如忘記大概錯誤地開釋內存屢屢會招致步驟運轉不正常乃至是步驟崩潰。為了減小開發職員的事情,同時增長體系的寧靜性與安定性,Java言語提供了渣滓吸收器來主動檢測目標的作用域,可主動地把不再被使用的存儲空間開釋掉。

具體而言,渣滓吸收器要賣力完成3項職責:分派內存、確保被引用目標的內存不被錯誤地吸收以及吸收不再被引用的目標的內存空間。

渣滓吸收器的存在一方面把開發職員從開釋內存的繁復事情中擺脫出來,提高了開發職員的消費聽從;另一方面,對開發職員屏蔽了開釋內存的辦法,可以制止因開發職員錯誤地利用內存而招致使用步驟的崩潰,確保了步驟的安定性。

但是,渣滓吸收也帶來了成績,為了完成渣滓吸收,渣滓吸收器必需跟蹤內存的使用情況,開釋沒用的目標,在完成內存的開釋后還必要處理堆中的碎片,這些利用一定會增長JVM的包袱,從而低落步驟的實行聽從。

對目標而言,假如沒有任何變量去引用它,那么該目標將不成能被步驟拜候,因此可以以為它是渣滓信息,可以被吸收。只需有一個以上的變量引用該目標,該目標就不會被渣滓吸收。

關于渣滓吸收器來說,它使用有向圖來紀錄和辦理堆內存中的一切目標,經過這個有向圖就可以識別哪些目標是“可達的”(有引用變量引用它就是“可達的”),哪些目標是“不成達的”(沒有引用變量引用它就是不成達的),一切“不成達”目標都是可被渣滓吸收的,示比如下:

上述代碼在實行到i2=i1后,內存的引用干系如下圖所示:

此時,假如渣滓吸收器正在舉行渣滓吸收利用,在遍歷上述有向圖時,資源2所占的內存是不成達的,渣滓吸收器就會以為這塊內存以前不會再被使用了,因此就會吸收該塊內存空間。

渣滓吸收都是依據一定的算法舉行的,底下先容此中幾種常用的渣滓吸收算法。

  1. 引用計數算法(Reference Counting Collector)

引用計數作為一種簡便但是聽從較低的辦法,其主要原理如下:在堆中對每個目標都有一個引用計數器;當目標被引用時,引用計數器加1;當引用被置為空或分開作用域的時,引用計數減1,由于這種辦法無法處理互相引用的成績,因此JVM沒有接納這個算法。

  1. 追蹤吸收算法(TracingCollector)

追蹤吸收算法使用JVM維護的目標引用圖,從根結點開頭遍歷目標的使用圖,同時標志遍歷到的目標。當遍歷完畢后,未被標志的目標就是現在已不被使用的目標,可以被吸收了。

  1. 緊縮吸收算法(CompactingCollector)

緊縮吸收算法的主要思緒如下:把堆中活動的目標挪動到堆中一端,如此就會在堆中別的一端留出很大的一塊空閑地區,相當于對堆中的碎片舉行了處理。固然這種辦法可以大大簡化消弭堆碎片的事情,但是每次處理都市帶來功能的喪失。

  1. 復制吸收算法(CopingCollector)

復制吸收算法的主要思緒如下:把堆分紅兩個輕重相反的地區,在任何時候,僅有此中的一個地區被使用,直到這個地區的被斲喪完為止,此時渣滓吸收器會中綴步驟的實行,經過遍歷的辦法把一切活動的目標復制到別的一個地區中,在復制的歷程中它們是緊挨著安插的,從而可以消弭內存碎片。當復制歷程完畢后步驟會接著運轉,直到這塊地區被使用完,然后再接納外表的辦法持續舉行渣滓吸收。

這個算法的優點是在舉行渣滓吸收的同時對目標的安插也舉行了安插,從而消弭了內存碎片。但是這也奉獻了很高的代價:關于指定輕重的堆來說,必要兩倍輕重的內存空間;同時由于在內存調停的歷程中要中綴如今實行的步驟,從而低落了步驟的實行聽從。

  1. 按代吸收算法(GenerationalCollector)

復制吸收算法主要的缺陷如下:每次算法實行時,一切處于活動形態的目標都要被復制,如此聽從很低。由于步驟有“步驟創建的大局部目標的生命周期都很短,僅有一局部目標有較長的生命周期”的特點,因此可以依據這個特點對算法舉行優化。按代吸收算法的主要思緒如下:把堆分紅兩個大概多個子堆,每一個子堆被視為一代。算法在運轉的歷程中優先搜集那些“年幼”的目標,假如一個目標顛末多次搜集仍舊“存活”,那么就可以把這個目標轉移到高一級的堆里,變小對其的掃描次數。

稀有口試題:

  1. 現有如下代碼:

當Float目標在第2行被創建后,什么時分可以被渣滓吸收?()

A.4行今后

B.5行今后

C.6行今后

D.7行今后

答案:C。在第6行后不再有目標引用Float目標了,因此可以被渣滓吸收。

2.下列關于渣滓吸收的說法中,準確的是()。

A.一旦一個目標成為渣滓,就立刻被吸收掉

B.目標空間被吸收掉之后,會實行該目標的finalize辦法

C.finalize辦法和C++的析構函數完善是一回事變

D.一個目標成為渣滓是由于不再有引用指著它,但是線程并非云云

答案:D。成為渣滓的目標,僅有本人次渣滓吸收器運轉時才會被吸收,而不是立刻被算賬,因此選項A錯誤。finalize辦法是在目標空間被吸收前調用的,因此選項B錯誤。在C++言語中,調用了析構函數后,目標一定會被燒毀,而Java言語調用了finalize辦法,渣滓卻不一定會被吸收,因此finalize辦法與C++的析構函數是不同的,以是選項C也不準確。關于D,當一個目標不再被引用后就成為渣滓可以被吸收,但是線程就算沒有被引用也可以獨立運轉的,因此與目標不同。以是準確答案為D。

3、對否可以主動關照JVM舉行渣滓吸收?

答案:由于渣滓吸收器的存在,Java言語本身沒有給開發職員提供顯式開釋已分派內存的辦法,也就是說,開發職員不克不及及時地調用渣滓吸收器對某個目標或一切目標舉行渣滓吸收。但開發職員卻可以經過調用System.gc()辦法來“關照”渣滓吸收器運轉,固然,JVM也并不會確保渣滓吸收器立刻就會運轉。由于System.gc()辦法的實行會中止一切呼應,去反省內存中對否有可吸收的目標,這會對步驟的正常運轉以及功能形成極大的要挾,因此實踐編程時,不保舉經常使用這一辦法。


版權聲明:本文來自互聯網整理發布,如有侵權,聯系刪除

原文鏈接:http://www.freetextsend.comhttp://www.freetextsend.com/qingganjiaoliu/41494.html


Copyright ? 2021-2022 All Rights Reserved 備案編號:閩ICP備2023009674號 網站地圖 聯系:dhh0407@outlook.com

www.成人网