內(nèi)蒙古呼倫貝爾職業(yè)技術(shù)學(xué)院 于世萍
Java垃圾回收器是java語言的根基,隨著硬件設(shè)備和java語言的發(fā)展,多個版本的java虛擬機在不同條件的硬件設(shè)備下表現(xiàn)的性能有所差異,選擇最合適的垃圾回收器可以提高基于java開發(fā)的系統(tǒng)的性能。本文分析了幾款主流的垃圾回收器,并在學(xué)校主流的辦公設(shè)備為實驗環(huán)境測試,該方法可應(yīng)用于OA系統(tǒng)開發(fā)時,配置合適時的垃圾回收器。
隨著java版本的更新,java的內(nèi)存回收算法也逐漸更新迭代,如今已經(jīng)提供了多種的垃圾回收器供開發(fā)人員選擇。面對不同性能的硬件設(shè)備和不同特征的場景,不同種類的垃圾回收器各有優(yōu)劣之分。對于開發(fā)人員而言,如果不去分析其執(zhí)行原理和算法特點,把自動內(nèi)存管理當(dāng)做黑匣子,只依賴最新版本的垃圾回收器,則不會帶來好的效果。
為實現(xiàn)在不同性能的設(shè)備上選擇最合適的垃圾回收器,本章將探究幾種垃圾回收器的工作原理和優(yōu)缺點。
引用計數(shù)法為每個分配的內(nèi)存空間保存一個引用計數(shù)器,統(tǒng)計有多少個內(nèi)存對象引用了這個空間。當(dāng)引用計數(shù)器的值為0時,表示該內(nèi)存空間不再使用,即可回收。雖然該方法實現(xiàn)簡單,判定效率高,但是該方法無法解決循環(huán)引用的問題,由于這個致命缺陷,如今的垃圾回收器已經(jīng)不再使用此類算法。
當(dāng)有效的內(nèi)存空間即將耗盡,則會停止程序的執(zhí)行,轉(zhuǎn)而進行標(biāo)記和清除兩項工作:首先從引用的根開始遍歷,標(biāo)記所有被引用過的對象,然后回收其余的沒有被引用的對象。該方法雖然可以有效的解決循環(huán)引用的問題,但是該方法的執(zhí)行效率不高,且執(zhí)行期間需要暫停整個應(yīng)用程序的正常執(zhí)行,導(dǎo)致用戶體驗不好,且由于回收的空間不連續(xù),產(chǎn)生了內(nèi)存碎片,需要維護一個空閑列表來解決內(nèi)存不連續(xù)的問題。
為解決標(biāo)記清除算法會產(chǎn)生內(nèi)存碎片的問題,提出了復(fù)制算法對標(biāo)記清除算法作了以下改進:將內(nèi)存空間分為兩塊,每次只使用一塊內(nèi)存。在執(zhí)行垃圾回收時,未被回收的內(nèi)存復(fù)制到另一塊內(nèi)存空間,并交換兩塊內(nèi)存空間的角色。復(fù)制的時候內(nèi)存空間會連續(xù)的排列好,由此可知,該方法解決了內(nèi)存碎片的問題。不過,復(fù)制算法的有效性是建立在內(nèi)存總空間較小,垃圾較多的情況下。如果需要垃圾回收的內(nèi)存空間多,每次回收的垃圾少,則會占用大量的時間進行復(fù)制操作。
該算法是在標(biāo)記清除算法上的改進,該方法執(zhí)行的第一步與標(biāo)記清除算法一樣,標(biāo)記所有被引用的對象,然后將存活的對象壓縮到一部分內(nèi)存區(qū)域,連續(xù)的排列,最后將清理所有存活對象之外的空間。這種操作解決了內(nèi)存碎片的問題,相較于空閑列表法,該方法的開銷顯然更小。
根據(jù)上述的研究可知,垃圾回收器的算法各有優(yōu)劣,如果可以根據(jù)內(nèi)存空間大小不同和垃圾與存活空間的比例不同,將內(nèi)存空間合理分配,在每一部分內(nèi)存空間使用不同的算法,即可達到取長補短的效果。為此,大部分的垃圾回收器會將內(nèi)存劃分為新生代和老年代兩塊區(qū)域,其中新生代占用總內(nèi)存空間的1/3,老年代占用2/3。首先新生成的垃圾被分配到新生代,新生代空間又分為一個eden區(qū)和兩個survivor區(qū)域。由于全部的內(nèi)存初始分配都在新生代進行,所以新生代的垃圾產(chǎn)生的較多,回收的頻率較高,所以新生代使用復(fù)制算法;當(dāng)新生代的內(nèi)存空間已滿切無法進行垃圾回收時,這些存活對象會被移動到老年代中。老年代的空間大,且很少會執(zhí)行垃圾回收。老年代占用總內(nèi)存空間的2/3,使用標(biāo)記壓縮算法,雖然該算法執(zhí)行的時間較長,但是老年代只負責(zé)回收新生代區(qū)域無法回收的內(nèi)存,且老年代的空間較大,很難全部耗盡。所以老年代執(zhí)行垃圾回收的次數(shù)遠少于新生代,執(zhí)行標(biāo)記壓縮算法的次數(shù)也很少。
如今的java語言已經(jīng)更新了十四個大版本,其中也更新了多個種類的垃圾回收器,以滿足在硬件環(huán)境的性能逐漸進步的條件下,充分利用硬件設(shè)備的性能,以達到更快速的執(zhí)行效率。目前主流的幾款垃圾回收期分別包括如下內(nèi)容。
Serial回收器是java語言第一代垃圾回收器,Serial回收器采用復(fù)制算法,應(yīng)用與新生代;Serial Old回收器采用標(biāo)記壓縮算法,應(yīng)用于老年代。整體次采用串行回收的方式。Serial是單線程的回收器,這不僅說明該回收器只有一個線程執(zhí)行垃圾回收,還表示執(zhí)行垃圾回收時,必須暫停所有工作線程,暫停工作線程期間,會造成應(yīng)用程序停頓。但是Serial垃圾回收器省去多個線程來回切換的開銷,對于限定單核cpu的環(huán)境來說,該方法仍然可以達到一定水平的工作效率。
ParNew回收器是在Serial回收器的基礎(chǔ)上擴展了并行回收的能力。在底層上,兩者共享了大部分的實現(xiàn)代碼,ParNew回收器同樣采用了復(fù)制算法和暫停用戶線程的機制,只是在垃圾回收執(zhí)行時,由多個線程執(zhí)行任務(wù)。在多核cpu的環(huán)境下,相較于Serial回收器,ParNew回收器執(zhí)行垃圾回收的速度要更快一些,用戶線程被暫停的時間就會短一些。ParNew回收器負責(zé)回收新生代,可搭配Serial Old回收器或者CMS回收器負責(zé)老年代的垃圾回收工作。
CMS垃圾回收器可以是實現(xiàn)并發(fā)工作,即垃圾回收線程在執(zhí)行某一部分操作時可以與用戶線程同時執(zhí)行。CMS負責(zé)老年代垃圾回收,基于標(biāo)記清除算法實現(xiàn)。其工作流程可分為初始標(biāo)記、并發(fā)標(biāo)記、重新標(biāo)記、并發(fā)清除四步驟。初始標(biāo)記負責(zé)定位一些立即回收的內(nèi)存空間,并發(fā)標(biāo)記查找一些與初始標(biāo)記過有關(guān)的且未被使用的內(nèi)存。并發(fā)標(biāo)記表示該步驟的垃圾回收線程與用戶線程可以同時執(zhí)行。重新標(biāo)記負責(zé)修正并發(fā)標(biāo)記期間由于垃圾回收線程與用戶線程可以同時執(zhí)行導(dǎo)致的錯誤標(biāo)記。并發(fā)清除負責(zé)回收垃圾,該步驟的垃圾回收線程與用戶線程任然可以同時執(zhí)行。該方法可以實現(xiàn)垃圾回收線程與工作線程在某些時段的同時工作,降低了由于垃圾回收造成工作線程停頓的時間。但是其缺點也很明顯:首先CMS采用標(biāo)記清除算法,必然會造成大量內(nèi)存碎片產(chǎn)生,無法合理的利用內(nèi)存空間。其次,CMS在并發(fā)標(biāo)記階段會對垃圾對象產(chǎn)生誤判,即該階段被判斷為不是垃圾的對象,用于工作線程也在執(zhí)行的原因,這些對象有可能在標(biāo)記結(jié)束后成為垃圾??傊瓹MS回收器在一次垃圾回收操作中無法準(zhǔn)確的回收所有的垃圾,當(dāng)垃圾增長過快時,該方法的性能明顯下降。
Parallel scavenge回收器同樣采用了復(fù)制算法,并行回收和暫停用戶線程機制。與parnew回收器區(qū)別在于該收集器以吞吐量優(yōu)先,并且會根據(jù)當(dāng)前程序的運行情況,動態(tài)的調(diào)整內(nèi)存分配情況,以達到吞吐量和延遲的可控制可協(xié)調(diào)。
G1收集器采用了與以上完全不同的分區(qū)方法,在垃圾回收期間,允許有多個線程同時工作,且擁有與應(yīng)用程序并發(fā)執(zhí)行的能力,不會完全阻塞工作線程。G1回收器將內(nèi)存空間劃分為多個區(qū),每個區(qū)之間采用復(fù)制算法,整體采用標(biāo)記壓縮算法。由于引入分區(qū)機制,G1可以自由控制垃圾回收線程的暫停時長,縮小回收范圍,優(yōu)先回收價值最高的區(qū),保證了在有限的時間內(nèi)獲取最高的回收效率。
為驗證在學(xué)校經(jīng)常使用中等配置的硬件設(shè)備與工作中主要使用的教務(wù)管理系統(tǒng)的場景下,以上介紹的幾種垃圾回收器的優(yōu)劣,本文設(shè)計的實驗如下:實驗運行兩個線程,第一個線程負責(zé)每秒打印一次時間,第二個線程通過循環(huán)生成字節(jié)數(shù)組占用內(nèi)存,當(dāng)達到一定的占用量后回收的操作,來模擬用戶使用教務(wù)管理系統(tǒng)。當(dāng)?shù)诙€線程回收內(nèi)存時,分別設(shè)置不同的垃圾回收器,來比較程序總共的運行時間,總運行時間=第一個線程的運行時間+垃圾回收占用的時間??倳r間越短,則表示垃圾回收執(zhí)行的時間越短,垃圾回收期的效果越好。表1為該實驗的執(zhí)行結(jié)果,由實驗結(jié)果可知,Parallel scavenge回收器的總時間最短,性能最優(yōu)。
表1 實驗結(jié)果對比
總結(jié):不同的垃圾回收器在不同的工作場景下各有優(yōu)劣性,一些新推出的垃圾回收器適用于互聯(lián)網(wǎng)B/S業(yè)務(wù),對處理高并發(fā)的業(yè)務(wù)請求有更好的效果,然而對于配置不高的單核cpu和簡單的教務(wù)管理系統(tǒng),反而使用早期的垃圾回收器的效果更好。