JVM是怎麼判斷不可用對象的

Java語言規範沒有明確地說明JVM使用哪一種垃圾回收算法,可是任何一種垃圾收集算法通常要作2件基本的事情:(1)發現無用信息對象;(2)回收被無用對象佔用的內存空間,使該空間可被程序再次使用。

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

一、 引用計數法(Reference Counting Collector) 引用計數法是惟一沒有使用根集的垃圾回收的法,該算法使用引用計數器來區分存活對象和再也不使用的對象。通常來講,堆中的每一個對象對應一個引用計數器。當每一次建立一個對象並賦給一個變量時,引用計數器置爲1。當對象被賦給任意變量時,引用計數器每次加1當對象出了做用域後(該對象丟棄再也不使用),引用計數器減1,一旦引用計數器爲0,對象就知足了垃圾收集的條件。

基於引用計數器的垃圾收集器運行較快,不會長時間中斷程序執行,適宜地必須 實時運行的程序。但引用計數器增長了程序執行的開銷,由於每次對象賦給新的變量,計數器加1,而每次現有對象出了做用域生,計數器減1。

二、tracing算法(Tracing Collector) tracing 算法是爲了解決引用計數法的問題而提出,它使用了根集的概念。基於tracing算法的垃圾收集器從根集開始掃描,識別出哪些對象可達,哪些對象不可達,並用某種方式標記可達對象,例如對每一個可達對象設置一個或多個位。在掃描識別過程當中,基於tracing算法的垃圾收集也稱爲標記和清除(mark- and-sweep)垃圾收集器.

三、compacting算法(Compacting Collector)

爲了解決堆碎片問題,基於tracing的垃圾回收吸取了Compacting算法的思想,在清除的過程當中,算法將全部的對象移到堆的一端,堆的另外一端就變成了一個相鄰的空閒內存區,收集器會對它移動的全部對象的全部引用進行更新,使得這些引用在新的位置能識別原來的對象。在基於Compacting算法的收集器的實現中,通常增長句柄句柄表。

四、copying算法(Coping Collector)

該算法的提出是爲了克服句柄的開銷和解決堆碎片的垃圾回收。它開始時把堆分紅 一個對象 面和多個空閒面,程序從對象面爲對象分配空間,當對象滿了,基於coping算法的垃圾 收集就從根集中掃描活動對象,並將每一個活動對象複製到空閒面(使得活動對象所佔的內存之間沒有空閒洞),這樣空閒面變成了對象面,原來的對象面變成了空閒面,程序會在新的對象面中分配內存。

一種典型的基於coping算法的垃圾回收是stop-and-copy算法,它將堆分紅對象面和空閒區域面,在對象面與空閒區域面的切換過程當中,程序暫停執行。

五、generation算法(Generational Collector)

stop- and-copy垃圾收集器的一個缺陷是收集器必須複製全部的活動對象,這增長了程序等待時間,這是coping算法低效的緣由。在程序設計中有這樣的規律:多數對象存在的時間比較短,少數的存在時間比較長。所以,generation算法將堆分紅兩個或多個,每一個子堆做爲對象的一代 (generation)。因爲多數對象存在的時間比較短,隨着程序丟棄不使用的對象,垃圾收集器將從最年輕的子堆中收集這些對象。在分代式的垃圾收集器運行後,上次運行存活下來的對象移到下一最高代的子堆中,因爲老一代的子堆不會常常被回收,於是節省了時間。
相關文章
相關標籤/搜索