JVM之GC常见算法
-
引用计数法(很少用):
使用一个计数器对堆中的对象被引用的次数进行统计,将没有被引用的对象进行清除
2.复制算法:
- 每次GC都会讲Eden区中的对象清到幸存区中,一旦Eden区被GC,那么Eden区就会是空的
- 两个幸存区保持谁空谁是to的原则,即每次GC回将上一轮的from区中的对象复制,然后加上Eden区中新的被GC进来的对象,合在一起放入空的to区中,然后to区变成下一轮的from区,原来的from区被清空,变成新一轮的to区
- 当一个对象经历了15次(默认值)GC还没有死,那么就会进入养老区中
注:可通过-XX:MaxTenuringThreshold +value 来调节进入养老区的时间,这也是JVM性能调优的一种方式
优点:没有内存碎片
缺点:浪费了内存空间,多了一半空间为空,加入存活率100%就会发生OOM,所以复制算法常用与存活率较低的新生区中
3.标记清除算法:
-
第一次扫描标记存活对象
-
第二次扫描清除没有被标记的对象
优点:不需要额外空间
缺点:时间复杂度高,有内存碎片
4.标记压缩算法:
前两步和标记清除算符一致
但是多了第三部,将存活对象移动到一起
优点:不需要额外空间,没有内存碎片
缺点:时间复杂度更高
二、总结
内存效率:复制算法>标记清除算法>标记压缩算法
内存整齐度: 复制算法=标记压缩算法>标记清除算法
内存利用率:标记压缩算法=标记清除算法>复制算法
所以,没有最好的算法,只有最合适的算法!所以JVM的GC=分代收集算法
-
年轻代存活率低,所以用复制算法,效率高
-
老年代存活率高,所以用标记压缩(内存碎片多的时候用)+标记清除算法(内存碎片不多的时候用)