java基础之垃圾收集器
概述
上一篇主要说了GC的过程,这里总结一下java的几种收集器和算法
前置结论
- 尽可能将对象分配到新生代,因为full GC成本高于minor GC
- 尽量少使用大对象
- JIT编译参数
- 发生oom时执行脚本 -XX:OnoomError=D:\reset.bat
- 获取GC日志 -Xloggc:D:\gclog.txt
- tomcat catalina.bat参数调优
算法
标记-清除
首先标记出所有需要回收的对象,标记完成以后统一进行回收。
标记过程参照上一篇不可达对象部分,其缺点有2个
- 效率问题,标记、清除过程效率都不高
- 空间碎片问题,当有较大对象的时候,不得不触发一次GC
复制算法
- 虽然这种算法实现简单,运行高效,但是代价太高。只能使用一半的空间。但是这种算法也带来一种思路,新生代中的对象 消失的很快,不需要按照1:1来分配,HotSpot默认Eden和Survivor1、Survivor2是8:1:1,当回收时,将Eden和Survivor(其中一个)一起复制到另外一块没有使用的Survivor中, 也就等于新生代有90%可以利用。
- 如果另一块Survivor没有足够的内存来接收上一次存活的对象,这些对象通过分配担保机制直接进入老年代。
- 复制算法比较适用于新生代。因为复制算法在存活对象比较多的时候,效率会降低,所以老年代不适用。
标记-整理算法
- 针对老年代的特点,与标记-清除算法的标记过程一样,但是之后是让所有存活的对象向另一端移动,然后直接清理掉边界以外的对象
- 既避免了内存碎片,也不需要两块相同的空间,性价比较高
分代收集算法
当前商业虚拟机都采用该算法,根据对象存活时期的不同,将内存分为几块,一般是分为新生代和老年代,在根据不同年代的不同特性来选择最适合的收集算法
- 新生代 复制算法
- 老年代 标记-整理算法
综上所述,收集器可以做以下分类 - 按照线程来分,串行收集器和并行收集器
- 按工作模式来分,并发式和独占式
- 按碎片处理方式,压缩式和非压缩式
- 按工作内存,新生代和老年代