【无标题】

【无标题】_第1张图片

标记清除:效率不高,扫描两次

Serial:适用于单核CPU,不用于多线程的切换

JDK1.8之前ParNEW+CMS

JDK1.8时候:Parallel Scaveng,Parallel Old

1)关注于吞吐量,GC回收次数少,但是回收周期比较长,CPU执行GC总共时间越短越好,所有线程集中精力所有线程做垃圾收集,那么这个垃圾收集的过程肯定是比较快的

2)CMS在进行垃圾收集的过程中还是要分一些CPU资源给到用户线程的,整个垃圾收集过程拉长了,整个垃圾收集的效率是不如Parallel,整个吞吐量会远远不如Parall Scaveng,所以对于大内存来说要使用CMS,来提升用户的体验,但是如果内存比较小,使用Parallel Scavenge也是可以的;

3)CMS不是内存空间满了才会fullGC,就是为了避免并发失败的情况,如果大对象比较多,可以把比例缩小,JVM内部会进行内置,如果上一次fullGC出发了,那么这一次CMS自动调整该参数调整的比较小一些,如果上一次FullGC没有触发,俺么这一次CMS调整该值就会调整的大一些

CMS主要是提高用户体验,牺牲了总共垃圾回收的总时间,但是STW的时间会更短

fullgc:收集整个堆,可能先是回收老年代

CMS:就是内存太大,要减少停顿时间,在总的GC的STW时间其实并没有缩短,可能还会更长,很多次间隔执行,用户感知不太大

初始标记:GCROOTS的直接引用对象,速度非常快,需要STW,因为要防止不断有新的引用产生,初始标记是做不完成的

并发标记:用户线程和GC并发执行,如果内存特别大,有很多很多对象,GC时间很长,用户体验感非常差,找到所有的GCROOTS引用链上的对象,占用80%的时间

重复标记:修复并发标记过程中可能有问题的对象,没有问题的对象突然变成存活的对象

并发清理:假设在并发清理过程中,应用程序和GC线程是同时执行的,之前并发标记已经将堆中的可达对象都进行标记了,假设此时如果老年代来了一个特别大的对象,这个时候有在执行并发清理,这个时候老年代的CMS不会再去执行标记过程,大对象到底是不是垃圾呢,因为它没有被标记过的,

并发重置:标记清楚掉

防止老年代跨代引用

这个分代年龄你设置的越小,缓存对象,Spring Bean对象,老不死的对象就可以尽早地进入到老年代,给伊甸区存放更多的空间给新生代的对象去使用,能够容纳更多的对象

可能出现多标了,但是如果GCroots被回收了,这些由GCROOTS引用链上面的垃圾就不再使用了,垃圾就变成浮动垃圾了,但是问题不大,下一次垃圾回收的时候进行回收就可以了

默认都是白色,黑色全都扫描过了,灰色的:没有分析完成,白色:没有访问

并发标记:会发生漏标

初始标记:

并发标记: 

重新标记:

浮动垃圾=多标=本来不是垃圾的,变成垃圾,多标,下一次垃圾回收解决

漏标=本来不是垃圾,变成垃圾,三色算法

元空间回收条件非常苛刻,遍历所有的类,类元信息都是孤立的

垃圾回收:

1)初始标记直接标记A,假设此时执行到2步骤的时候开始执行并发标记

2)如果并发标记过程中,如果这个对象成员变量所引用到的对象都被扫描过了,那么这个节点就变成黑色了,如果A扫描过了B和D(null),那么A在并发标记过程中就变成黑色了,凡是标记成黑色的对象在后续进行垃圾回收的时候不会做任何处理,因为这个对象肯定是一个非垃圾对象;

3)灰色对象:在代码中,B有两个成员变量,B中的C和D是存在引用的,C 和D没有任何的引用也就意味着C D不在引用任何成员变量了,如果在进行扫描B的时候,B已经扫描过C了,但是此时B还没有来得及扫描到D,此时B就会标记成灰色,因为此时B中的成员变量D对象还没有来得及扫描,如果在可达性分析算法中如果扫描B的过程中还没有扫描D,D就是白色,C因为已经被D扫描过了,但是C还没有任何成员变量,也相当于是黑色此时C会标记成黑色

4)开始出现漏标:先把从B到D上面的引用链置为空,然后再让已经标记成黑色的A的成员变量的d指向B上面的D,B找不到D,但是A已经扫描过了,A已经变成黑色了,此时A不会再扫描,但是此时B还扫描不到D,此时D就被当做是垃圾回收了,按照三色标记算法,D会被清理掉,这就叫做误删除

1)增量更新:新增的引用,赋值操作事多了一条引用链,会把赋值新增的引用,会创建一个集合会存放起来来存放引用关系,在重新标记的过程中解决并发标记过程中漏标的情况,重新标记的过程中时会造成STW的,漏标是一定会处理,重新标记的过程中会去寻找新增的这些引用,重新去扫描,记录的是a.d=d,会从GCroots重新扫描,在这个扫描过程中会把A重新标记成灰色,这个时候还是会重新扫描A的所有的成员变量,最终将D变成黑色的对象,A也会变成黑色的对象,此时是不会回收D的,因为重新标记是STW的,整个所有的对象图是不会发生变化的,再写之后将引用关系放到集合中,是写后屏障

2)原始快照:SATB,在并发标记过程把D置为空,于是就中把D放在一个集合中,以后都不会再动D,就把D当成一个浮动垃圾,下一次垃圾回收的时候再来进行处理,当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后,再将这些记录过的引用关系中的灰色对象为根,在写之前将删除的引用放到集合中,是写前屏障

写屏障:新增引用和赋值删除引用都是通过写屏障来进行操作的,在赋值之前做,在赋值之后做把引用丢到集合里面,在写操作的前面和后面做一些操作,把引用收集到集合里面,集合在C++底层就是使用的是内存队列;

卡表和记忆集:
 

你可能感兴趣的:(java,开发语言)