1.GC的作用区域实际只有堆+方法区,大部分在堆中
2.JVM在进行GC时,并不是对这三个区域统一回收,大部分时候,回收都是新生代
*新生代
*幸存区(from,to)
*老年区
GC两种类:轻GC(普通的GC),重GC(全局的GC)
记录每一个对象的引用数,如果引用为0,进行回收
复制算法:复制算法主要是伊甸园区,两个幸存区来回复制
复制算法的GC就是每经历一次GC,Eden中存活下来的对象次数加1并复制到幸存区to中,幸存区from中的仍然存活下来的对象同样加1复制到幸存区to中,然后from和to交换位置(因为谁空谁是to),当幸存区from满了,或者有对象次数达到15次,就将该对象移到养老区.
复制算法
*好处:没有内存的碎片
*坏处:浪费了内存空间,多了一半空间永远是空的(幸存区to).假设对象100%存活(极端情况),内存OOM
复制算法最佳使用场景:对象存活度较低的时候,即新生区
1.扫描这些对象,对活着的对象进行标记
2.清除:对没有标记的对象,进行清楚
(两轮扫描)
优点:不需要额外的空间
缺点:两次扫描,严重浪费时间,会产生内存碎片
(当所有的对象都被标记,也会OOM)
再优化
多一步压缩,再一轮扫描,向一端移动存活对象,多了一个移动成本,可以防止内存碎片产生
再优化:
先标记清除几次之后再来标记压缩,比如五轮标记清除之后,来一轮压缩
GC总结
内存效率:复制算法> 标记清除>标记压缩(时间复杂度)
内存整齐度:复制算法=标记压缩>标记清除
内存利用率:标记压缩=标记清除>复制算法
没有最好的算法,只有最合适的算法—>GC:分代收集算法
即:
年轻代:存活率低,一般用复制算法
老年代:区域大,存活率高,一般用标记清除(内存碎片不是太多)+标记压缩混合实现 (jvm调优实际就是调这个,看进行多少次标记清除,再进行标记压缩,效率最好,只要内存碎片不是太多,都可以再进行标记清除,然后再碎片很多再标记压缩,直到OOM)



