java垃圾回收

以下内容的jdk版本为1.7

1、寻找可回收的对象

1.1 计数器:计算引用对象的引用数量。缺点 无法解决循环引用的问题
1.2 可达性分析:不可达的对象会进行标记并筛选(是否执行过finalize方法、是否覆盖finalize方法)如果没有执行过则放进一个队列,由虚拟机执行队列中的对象的finalize方法(方法内可以将引用指向给gcroot可达的对象,在下次执行gc的时候就不会回收了,指向引用需要在下一次gc之前指向)

2、枚举根节点 gc Root

2.1、虚拟机在加载完类的时候会在特定位置上记录下栈和寄存器中哪些位置是引用(应该是记录常量跟静态属性的引用),并将这些引用存入一个oopMap的数据结构
2.2、在oopMap的协助下,虚拟机可以快速的完成gcRoot的枚举
2.3、虚拟机不会为每条指令生成oopMap标记,如上所说,特定位置,这些特定位置叫做安全点(不能太少导致gc频率太低,也不能太多导致gc频率太高,所以安全点的选定是要求程序具有长时间运行的 特征)
2.4、如何让程序都跑到安全点上并且停下来:1、抢先式中断:在gc发生时,将所有线程中断,如果中断的线程不在安全点上,就放开直到跑到安全点上为止主动式中断:不直接对线程操作,仅仅设置一个标志,各个线程在执行的时候主动轮训这个标志, 如果为真就挂起当前线程

3、垃圾回收算法

3.1:标记-清除 标记需要回收的内存空间,然后统一清除 缺点会产生大量的不连续内存空间,在分配大对象时,可能无法找到连续的内存空间
3.2:复制算法 将不需要回收的对象复制到另一块内存中,然后删除当前使用的内存 缺点是需要50%的内存作为复制内存
3.3:标记-整理 与标记清除的第一个步骤一样 但是标记完将不需要回收的对象向一端移动,然后删除端边界以外的内容
3.4:上述的算法没有最好的,所以根据堆内存中不同年代的对象使用不同的收集算法当前商业虚拟机的垃圾收集都采用 “分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同
将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。

4、垃圾收集器

4.1、Serial收集器、Serial Old收集器(老年代),暂停所有线程,进行垃圾收集,是单线程的。
4.2、ParNew收集器 暂停所有线程,进行垃圾收集,是多线程的
4.3、Parallel Scavenge收集器、Parallel Old收集器(老年代版本),跟4.2收集器实质上没有什么区别,不过他提供了两个参数,垃圾收集时线程停顿的时间还有设置吞吐量的大小。-XX:MaxGCPauseMillis参数以及直接设置吞吐量大小的-XX:GCTimeRatio参数。Parallel Scavenge收集器还有一个参数-XX:+UseAdaptiveSizePolicy值得关注。这是一个开关参数,当这个参数打开之后,就不需要手工指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会自动分配内存,是一个自适应调节的垃圾收集器
4.4、CMS收集器 有四个过程,初始标记(标记一下gcRoot能直接关联的对象),并发标记(是进行可达性分析的过程,可以跟用户线程一起执行),重新标记(修正并发标记区间标记产生变化的标记),并发清除(清除,可以跟用户线程一起执行)CMS是采用标记清除算法的,有一个参数控制在进行第几次fullGc的时候进行标记-整理CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数(默认就是开启的),用于在CMS收集器顶不住要进行FullGC时开启内存碎片的合并整理过程,内存整理的过程是无法并发的,空间碎片问题没有了,但停顿时间不得不变长。虚拟机设计者还提供了另外一个参数-XX:CMSFullGCsBeforeCompaction,这个参数是用于设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值为0,表示每次进入FullGC时都进行碎片整理)。
4.5、g1收集器,跟cms类似,不过不需要其他收集器配合就能管理整个堆。跟踪各个区域中垃圾堆积的价值大小(所需时间以及回收后空间的大小),优先回收价值大的区域。g1中每个区域都有对应的Remembered Set,在引用数据赋值的时候会检测引用的数据是否处于不同的区域中,如果处于不同的区域中则通过carttable记录在被引用对象的Remembered Set中

本人没事写的东西,有错误之处欢迎指正。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享