一、对象存活判断
引用计数:每个对象都有引用计数属性,新增一个引用时计数+1,引用释放时计数-1,当计数为0时可以回收。此方法无法解决对象相互循环引用的问题。
可达性分析:从GC Roots向下开始搜索,搜索走过的路径称为引用链,当一个对象到GC Roots 没有任何引用链相连时,则该对象是不可用对象。
GC Roots 包括以下:
JVM栈中引用的对象
方法区中类静态属性实体引用的对象
方法区中常量引用的对象
本地方法栈中java本地接口(JNI)引用的对象
二、垃圾收集算法
标记-清除算法(Mark-Sweep)
算法分为两个阶段:标记和清除。
标记:标记出所有需要回收的对象;清除:在标记完成后统一回收掉所有被标记的对象。
缺点:
标记和清除的效率都不高。
标记 清除之后会产生大量不连续的碎片,在之后如果需要分配较大的对象时无法找到足够的连续内存,从而不得不提前触发另一次垃圾收集动作。
复制算法(Copying)------不适合老年代
把可用内存分成大小相等的两块,每次使用其中的一块,使用完这块后就将还存活的对象复制到另一块上,然后把已使用的内存空间一次清理掉。
不用考虑内存碎片的问题,运行高效。
但是这种算法将内存缩小为原来的一半,持续复制长生存期的对象会导致效率降低。
标记-压缩算法(Mark-Compact)
和标记-清除算法类似,但是在后续步骤中不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。
分代收集算法(Generational Collection)
把java堆分为新生代和老年代。在新生代中,每次垃圾收集时都有大批的对象死去,只有少量存活,可以选择复制算法,只需要付出少量存活对象的复制成本就可以完成收集;在老年代中,对象存活率高,没有额外的空间对它进行分配担保,就需要使用标记-清除和标记-整理的算法来回收。
三、垃圾收集器
---------串行和并行的理解:
串行是指多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个。并行指的是多个任务可以同时执行。
serial收集器(串行收集器)
是最古老、最稳定、效率较高的单线程收集器,新生代和老年代使用串行回收(新生代复制算法,老年代标记-压缩算法);在垃圾收集过程中会服务暂停(Stop The World)。----------什么是STW?
STW:在执行垃圾收集算法时,java其他应用程序的线程都被挂起的状态
参数控制:-XX:+UseSerialGC --------串行收集器
ParNew收集器
Serial收集器的多线程版。
新生代中并行,采用复制算法;老年代中串行,采用标记-压缩算法。
参数控制:-XX:+UseParNewGC --------ParNew收集器
-XX:ParallelGCThreads--------限制线程数
Paraller收集器
类似于ParNew收集器,Paraller收集器可以使用参数打开自适应调节策略。
新生代使用复制算法,老年代使用标记-压缩算法。
参数控制:-XX:+UseParallerGC ---------使用Paraller收集器+老年代串行
ParallerOld收集器
JDK1.6以后提供的收集器,使用多线程和标记-压缩算法。
参数控制:-XX:+UseParallerOldGC ---------使用Paraller收集器+老年代并行
CMS收集器
一种以获取最短回收停顿时间为目标的收集器。基于 标记-清除 算法实现的收集器,如下是步骤:
初始标记
并发标记
重新标记
并发清除
初始标记阶段:仅仅只是标记一下GC Roots能直接关联到的对象,速度快。
并发标记阶段:进行GC Roots Tracing(可达性分析)的过程。
重新标记阶段:修正并发标记期间,应用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。
优点:并发收集、停顿低。
缺点:产生大量的空间碎片 ,并发阶段会降低吞吐量。
参数控制:-XX:+UseConcMarkSweepGC --------使用CMS收集器
-XX:+UseCMSCompactAtFullCollection ---------FullGC后进行一次碎片整理
-XX:+CMSFullGCsBeforeCompaction ----------设置进行几次FullGC后,进行一次碎片整理
-XX:ParallerCMSThreads ---------设定CMS的线程数目(一般约等于CPU数)
G1收集器
与CMS收集器相比,G1收集器有以下特点:
空间整合:G1收集器采用标记-压缩算法,不会产生空间碎片,在分配大对象时不会因为找不到连续空间而提前触发下一次GC。
可预测停顿:能够让使用者明确指定在一个长度为N毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒
G1收集器的收集步骤:
标记阶段:初始标记,这个阶段会STW,并且触发一次普通Mintor GC。
扫描根区域(Roots Region Scanning):程序运行过程中会回收survivor区(存活到老年代),此过程需要在young GC前完成。
并发标记(Concurrent Marking):此过程可能会被young GC打断,若发现区域对象中的所有对象都是垃圾,这个区域会被立即回收。
再标记(Remark):会有短暂的STW,此阶段用来收集并发标记阶段产生新的垃圾(并发标记阶段和应用程序一同运行)。G1采用了比CMS更快的初始快照算法(SATB)。
复制/清除(Copy/Clean up):多线程清除失活对象,会有STW,G1将回收区域的存活对象拷贝到新区域,清除Remember Sets,并发清空回收区域并把它返回到空闲区域链表中。
四、常用的收集器组合