垃圾回收-GC
三个问题
哪些内存需要回收?
什么时候回收?
如何回收?
新生代引发的GC叫YoungGC
老年代引发的GC叫FullGC
FullGC会引起整个Jvm的用户线程暂停,待垃圾回收完毕后,才继续运行(严重影响性能)
确定对象“存活”还是“死去”
引用计数算法
根搜索算法(GC Roots)
引用的定义: 如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表一个引用
永久代回收“性价比”比较低
主要回收
废弃的常量
无用的类
类的所有实例都已经被回收
该类的Class对象没有在任何地方被引用
堆垃圾回收算法
标记-清除算法
特点 :
分为“标记”和“清除”两个阶段
标记完成后,统一回收
缺点 :
效率,标记和清除过程效率都不高
空间,标记清除后会产生大量不连续的内存碎片(内存使用都是连续的)
复制算法
特点:
内存分为相等的两块
当一块内存用完,将存活对象复制到另外一块中,
原内存一次性清理掉 复制时按照顺序分配内存,
无内存碎片问题
新生代使用此算法
缺点: 将内存分为两半,利用率低
标记-压缩算法
特点:
先对存活对象进行标记
让所有存活对象向一边移动
清理掉存活对象边界外的所有内存
注:老年代使用此算法
分代收集算法
缺点:效率低
分代收集算法
当代的商业虚拟机都采用“分代收集”
根据对象的存活周期的不同将内存划分成几块,一般Java堆分为新生代和老年代
新生代采用复制算法
老年代采用标记-压缩算法
垃圾收集器
垃圾收集器是内存回收算法的具体实现
没有完美的收集器
Jvm不同的区域可以采用不同的垃圾收集器组合,主要有:
Serial收集器(串行)
单线程收集器
用户线程全部停止(Stop the world)
Client模式下,新生代默认收集器
优点:简单、高效
ParNew收集器(并行)
并行收集器,Serial收集器的多线程版本
Server模式下Jvm默认的新生代收集器
默认开启的垃圾回收线程与cpu核数一致
CMS收集器(并发(边运行边运行))
并发收集器(ConcurrentMarkSweep)
采用了标记-清除算法
并发收集、低停顿
缺点:
消耗cpu
会产生内存碎片
浮动垃圾(Concurrent Mode Failure)