有了各自独立的可清除区域后,这才出现了众多不同的回收算法,正是它们一直以来在持续提升着GC的性能。
这并不说明这样的方式是没有问题的。比如说,不同分代中的对象可能彼此间有引用,在进行分代回收时,它们便为视为是“事实上”的GC根对象(GC roots)。
而更为重要的是,分代假设对于某些应用来说并不成立。由于GC算法主要是为那些“快速消失”或者“永久存活”的对象而进行的优化,因此对于那些生命周期“适中的对象,JVM就显得无能为力了。
内存池
在堆里面进行内存池的划分对大家来说应该是非常熟悉的了。不过大家可能不太清楚的是在不同的内存池中,垃圾回收是如何履行它的职责的。值得注意的是,虽然不同的GC算法细节实现上有所不同,但是本章中所提到的概念却是大同小异的。
伊甸区(Eden)
新对象被创建时,通常便会被分配到伊甸区。由于通常都会有多个线程在同时分配大量的对象,因为伊甸区又被进一步划分成一个或多个线程本地分配缓冲(Thread Local Allocation Buffer,简称TLAB)。有了这些缓冲区使得JVM中大多数对象的分配都可以在各个线程自己对应的TLAB中完成,从而避免了线程间昂贵的同步开销。
如果在TLAB中无法完成分配(通常是由于没有足够的空间),便会到伊甸区的共享空间中进行分配。如果这里还是没有足够的空间,则会触发一次新生代垃圾回收的过程来释放空间。如果垃圾回收后伊甸区还是没有足够的空间,那么这个对象便会到老生代中去分配。
当进行伊甸区的回收时,垃圾回收器会从根对象开始遍历所有的可达对象,并将它们标记为存活状态。