1.对象是否存活方法
- 引用计数法:给对象添加一个计数器,有对象引用时计数器+1,失去对象引用时-1,当计数器为0时,表示对象可以回收。该算法不能解决对象相互引用的问题。如A对象内部引用B,B对象内部引用A,此时虽然外部没有对象引用,但是他们的计数器不为0,不能回收。
- 可达性分析法:通过起始节点(GC roots)向下搜索,搜索走过的路径称为引用链,当一个对象到GC root没有引用链相连时,则表明此对象不可达,可以回收。
- finalize:没有引用链的对象会进行一次标记,放入到F-QUEUE中,系统开启线程执行finalize()方法进行第二次标记,此时在finalize方法中可以让对象重新引用。第二次标记仍没有引用的将会被回收。
- 引用概念
jdk1.2之后对引用的概念进行了扩充。当内存空间充足时,对象可以保存在内存之中,当内存紧张时,则抛弃这些对象。
- 强引用:Object obj = new Object()。只要强引用在,垃圾收集器不会回收引用的对象。
- 软引用:SoftReference,用来描述一些还有用但非必须的对象。对于软引用关联的对象,在系统发生内存溢出之前,会对软引用关联的对象列入回收范围进行第二次内存回收,此时如果还是内存不足,则会抛出内存溢出异常。
- 弱引用:WeakReference,也是用来描述一些非必须的对象,被弱引用关联的对象只能生存到下一次垃圾回收前。
- 虚引用: PhantomReference,最弱的一种引用,虚引用的存在不会对对象的生命周期产生影响,也不能通过它获取对象实例,存在唯一理由是可以在系统回收这个对象时收到一个通知。
- 垃圾收集算法
- 标记清除算法
对回收对象进行标记->统一回收标记对象
缺点:效率低-标记和回收效率都很低。空间-容易造成空间碎片,碎片过多会造成在分配一次大对象时因为连续内存不足而引起下一次GC - 复制算法
将内存分为两块,当一块的使用完时,将存活的对象复制到另外一块,同时清理对已经使用过的进行一次垃圾回收。现在的虚拟机大多使用此种方法划分新生代,因为新生代具有'朝生夕死' 的现象,一般将新生代按8:1:1的比列分为Eden区和两个Survior区。对象时在Eden区创建的,当Eden空间不足时,会触发第一次GC,此时还存活的对象会复制到From Survior区,并年龄+1,当触发第二次GC时,将Eden区和From Survior区还存活的对象复制到To Survior区,并清空Eden和From Survior区内存,同时对象GC年龄+1,当对象GC年龄超过阈值时,对象会被放到老年代。 - 标记-整理算法
老年代算法,先对可回收对象进行标记,再回收并对回收后的内存进行整理,是的存活的对象都向内存一边移动,使其变成连续内存。 - 分代收集算法
新生代和老年代使用不用的算法
- 垃圾如何被回收
- 安全点 safepoint:HotSpot虚拟机记录特定OopMap(存放对象的引用)位置的点。
GC时,线程到安全点中断线程。主动式中断:GC时,设置中断标志,线程轮询中断标志,并到安全点挂起线程。抢断式中断:GC时,中断所有线程,若线程不在安全点,则启动线程运行到安全点中断。 - 安全区域 safeRegion:
安全区域是指在一段代码片段中引用关系不会发生变化,在这一区域的任何地方发生GC都是安全的。解决线程不执行(即没有分配CPU时间片,如sleep和block)的情况,此时线程不能轮询或者响应中断。
线程执行到安全区域时,首先标记自己已经进入安全区域,那样,发生gc时,不用管处于安全区域的线程。当线程执行完安全区域的代码时,首先检查GC是否已经完毕,否则需要等到GC完毕的信号。
-
垃圾收集器
HotSpot垃圾收集器.png
-
Serial收集器
单线程,串行,新生代使用,使用复制算法。 -
ParNew收集器
Serial收集器的多线程版本。
-XX:+UseParNew指定ParNew收集器,他可以与老年代收集器CMS配合使用,是目前新生代使用最多的收集器
-XX:+ParallelGCThreads限制垃圾收集线程数 -
Parallel Scavenge收集器
新生代收集器,使用复制算法的并行收集器
Paralle Scavenge收集器关注点在吞吐量(吞吐量= 代码运行时间 / (代码运行时间+垃圾收集时间)),
-XX:+MaxGCPauseMills:最大垃圾回收停顿时间
-XX:+GCTimeRatio:直接设置吞吐量大小(吞吐量的倒数)
-XX:+UseAdaptivePolicy:自适应调节策略。打开此开关,不需要手动设置Eden区和Survior区的比例,晋升老年代的年龄大小了,虚拟机会依据当前系统的运行情况自行设置。只要把基本数据设置好(如-Xmx最大堆),然后使用-XX:UseMaxGcPauseMills或者-XX:+GCTimeRatio即可。 -
Parallel Old收集器
Prallel Scavenge的老年代版本。使用多线程和标记-整理算法
配合Parallel Scavenge使用 -
CMS收集器
一种以获取最短停顿时间的收集器,使用标记-清楚清除算法。
初始标记:仅仅是标记GC root能关联的对象,速度很快,需要停顿。
并发标记:进行GC ROOT Tracing的过程,时间久
重新标记:修正并发标记阶段因用户程序继续运行而导致标记发生变动的那一部分对象的标记记录。耗时比初始标记长,但没有并发标记长。
并发清除:垃圾收集
由于整个过程并发收集和并发清除都是和用户线程一起工作的,所以总体上,CMS收集器的内存回收过程是与用户线程一起并发执行的。
缺点:
对CPU资源敏感;
无法处理浮动垃圾(在并发清除过程中产生的垃圾,只能等到下次GC才能处理,称为浮动垃圾);
基于标记清除算法,会造成大量碎片。-XX:+UseCMSCompactAtFullCollection 该开关可以控制在CMS在顶不住要full gc时进行空间碎片整理。此方法会造成停顿时间延长。
-XX:+CMSFullGCsBeforeCompaction,用于控制执行多少次不压缩的Full gc后,跟着来一次带压缩的。 -
G1
优势:并行并发,分代收集,空间整合,可预测的停顿
垃圾收集步骤:
初始标记:找到GC ROOT关联的对象。需要停顿
并发标记:从GC ROOT开始对堆中的对象进行可达性分析,找出活的对象。
最终标记:修正在并发标记期间因用户程序继续执行而导致产生变动的标记记录。需要停顿,但是可以并行执行
筛选回收:对个region的回收价值进行排序,根据用户期望的GC停顿时间来指定回收计划。
网友评论