有了各自獨(dú)立的可清除區(qū)域后,這才出現(xiàn)了眾多不同的回收算法,正是它們一直以來在持續(xù)提升著GC的性能。
這并不說明這樣的方式是沒有問題的。比如說,不同分代中的對(duì)象可能彼此間有引用,在進(jìn)行分代回收時(shí),它們便為視為是“事實(shí)上”的GC根對(duì)象(GC roots)。
而更為重要的是,分代假設(shè)對(duì)于某些應(yīng)用來說并不成立。由于GC算法主要是為那些“快速消失”或者“永久存活”的對(duì)象而進(jìn)行的優(yōu)化,因此對(duì)于那些生命周期“適中的對(duì)象,JVM就顯得無能為力了。
內(nèi)存池
在堆里面進(jìn)行內(nèi)存池的劃分對(duì)大家來說應(yīng)該是非常熟悉的了。不過大家可能不太清楚的是在不同的內(nèi)存池中,垃圾回收是如何履行它的職責(zé)的。值得注意的是,雖然不同的GC算法細(xì)節(jié)實(shí)現(xiàn)上有所不同,但是本章中所提到的概念卻是大同小異的。
伊甸區(qū)(Eden)
新對(duì)象被創(chuàng)建時(shí),通常便會(huì)被分配到伊甸區(qū)。由于通常都會(huì)有多個(gè)線程在同時(shí)分配大量的對(duì)象,因?yàn)橐恋閰^(qū)又被進(jìn)一步劃分成一個(gè)或多個(gè)線程本地分配緩沖(Thread Local Allocation Buffer,簡(jiǎn)稱TLAB)。有了這些緩沖區(qū)使得JVM中大多數(shù)對(duì)象的分配都可以在各個(gè)線程自己對(duì)應(yīng)的TLAB中完成,從而避免了線程間昂貴的同步開銷。
如果在TLAB中無法完成分配(通常是由于沒有足夠的空間),便會(huì)到伊甸區(qū)的共享空間中進(jìn)行分配。如果這里還是沒有足夠的空間,則會(huì)觸發(fā)一次新生代垃圾回收的過程來釋放空間。如果垃圾回收后伊甸區(qū)還是沒有足夠的空間,那么這個(gè)對(duì)象便會(huì)到老生代中去分配。
當(dāng)進(jìn)行伊甸區(qū)的回收時(shí),垃圾回收器會(huì)從根對(duì)象開始遍歷所有的可達(dá)對(duì)象,并將它們標(biāo)記為存活狀態(tài)。