1.串行垃圾回收器
单线程,适用场景:堆内存较小,适用于个人电脑
通过设置UseSerialGC =Serial+SerialOld Serial是管理新生代的垃圾回收器,采用的是复制算法,SerialOld是管理的老年代的垃圾回收器,采用的是标记整理算法。
讲一下整个流程:
一开始多个cpu在运行时,当堆内内存不够时,发生垃圾回收,此时用户线程到一个安全点停下来,垃圾回收线程开始运行,等到垃圾回收线程运行完成,用户线程开始工作。
问题一:这些用户线程为什么要停下来?
因为在垃圾回收时,某些对象的内存地址会发生改变,当其他用户线程访问的时候,可能访问会问空。
2.吞吐量优先
多线程,单位时间内,保证stop the world时间最短。比如说:每次stw时间为0.2,总共2次垃圾回收,总时间为0.4
第一个参数是控制新生代大小,第二个参数是控制垃圾回收时间和总时间的一个占比1/1+radio,比如说radio为99,垃圾回收时间不能超过总时间的1%,第三个参数是最大暂停时间,这里默认是200ms,第四个参数是线程数。这里有一个问题:第二个线程和第三个线程是有冲突的,往往我们为了达到时间尽可能地少,我们会调大堆内存,但是调大堆内存,最大暂停时间就会减少。
3.响应时间优先
多线程,保证每一次stop the world时间最短。比如说:每次stw时间为0.1。
首先讲一讲如何保证的每一次stw时间很短的,因为除了初始标记和重新标记之外会stop the world,其他时候都是和用户并发进行的,因此stw的时间就缩短了,但是其吞吐量减少了,因为有一个线程用来作为垃圾回收线程,因此相比于吞吐量优先垃圾回收器,少了一个线程执行任务。
接下来讲一讲工作流程。CMS--->concurrent mark sweep
CMS是一款针对于老年代的垃圾回收器,当老年代内存空间不足时,开始初始标记,此时要stop the world,这个时候stw时间很短,因为初始标记只标记一些根对象,然后并发标记,这个时候是和用户线程并发进行的,接下来又重新标记,这个时候要stw,为什么要stw呢,因为在并发标记时,用户线程改变一些对象的引用或者产生了一些新的对象,这个时候需要重新标记,最后就是并发清理,但是在并发清理的过程中有一个新的问题就是会产生新的垃圾,这些垃圾要等到下一次垃圾回收才能被清理,这些垃圾叫浮动垃圾,因此,第三个参数是用来设置老年代内存达到65%(默认),就开始垃圾回收,另外一些内存用来存放浮动垃圾。还有问题就是在重新标记阶段,有一个特殊的场景就是新生代对象引用老年代对象,这个时候要扫描整个堆进行垃圾回收,而新生代数量一般比较多,这样效率不是很高,因此第四个参数的设置就是用来解决这个问题,首先进行一次垃圾回收,然后再进行标记。
最后一个问题:因为老年代是标记清除算法,这里会产生内存碎片,当产生新的对象,内存不足时,会出现并发失败,垃圾回收器就会退化成serialOld(标记整理).