这里有三种垃圾回收算法,分别是标记清楚、标记整理、复制算法
1.标记清除
在进行垃圾回收时,扫描堆区的对象,判断它是否是垃圾,就从根对象开始是否可以找到该对象,如果可以找不到,则标记为垃圾,等到垃圾回收的时候要就清理。这里的清理并不是清0,而是将这一块的内存首尾地址记录到空闲队列当中。优点是:回收速度很快,缺点是会产生内存碎片。
2.标记整理
与标记清除同样的做法,扫描堆区的对象,先标记,然后在清除的过程中将可用的对象向前移动,使内存更紧凑,这样连续的空间就比较多了。就不会有内存碎片的问题。缺点是速度慢。
3.复制算法
这里有两块区域,一个是From区域,一个是To区域。首先标记,然后将存活的对象移动到to区,然后清理掉from区,最后进行交换。
这三种算法并不是只能使用一个,而是结合使用。对于三种算法的应用是分代垃圾回收。
分代垃圾回收机制
首先介绍一下堆内存的结构:
堆内存被划分为两个区域,一个是新生代,一个是老生代。新生代被划分为伊甸园区、幸存区From、幸存区To
第一个问题:为什么需要划分新生代和老年代?
因为java对象有时候需要长时间引用,有些java对象被用完就被回收了。针对不同的生命周期有不同的垃圾回收策略.新生代处理的是朝生夕死的对象,而老年代处理的是长期存活的对象。不同的区域有不同的算法进行垃圾回收,这样会更有效率。
当对象被创建的时候,会首先放在伊甸园区,随着对象一直被创建,伊甸园区会被逐渐放满,当出现新生代内存不足时,此时会发生MinorGC(这个时候会stop the world),首先标记没有被GCRoot引用的对象,将引用的对象放入幸存区中的to区,并且对其年龄计数+1.然后交换from。当发生第二次MinorGC的时候,会同时清理伊甸园区和From区。等到幸存区中的对象年龄达到15之后,就被放到老年代中。这里会有两种情况发生FullGC.
1.新生代对象年龄达到了,进入到老年代,此时老年代存放不下。
2.当新生代的对象比较大,存放不下,这个时候也会FullGC。
Fullgc采用的是标记清除算法或者标记整理。