【垃圾收集】JVM的垃圾回收器有哪些特点?
●JVM如何进行垃圾回收?
●JVM垃圾回收算法有哪些?
面试官上线啦
新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。具体原理见上一篇文章。
老年代GC(Major GC / Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。
串行垃圾回收器: 串行垃圾回收器在进行垃圾回收时,它会持有所有应用程序的线程,冻结所有应用程序线程,使用单个垃圾回收线程来进行垃圾回收工作。串行垃圾回收器是为单线程环境而设计的,如果你的程序不需要多线程,启动串行垃圾回收。
并行垃圾回收器: 并行垃圾回收相对于串行,是通过多线程运行垃圾收集的。也会stop-the-world。适合Server模式以及多CPU环境。一般会和jdk1.5之后出现的CMS搭配使用
Serial收集器的多线程并行版本,除了使用多线程之外,其余参数和Serial一模一样; 它是目前新生代首选的垃圾回收器,因为除了ParNew之外,它是唯一一个能与老年代CMS配合工作的,复制算法
可以通过参数-XX:ParallelGCThreads来设置线程数。
使用-XX:+UseParNewGC参数可以设置新生代使用这个并行回收器
就是非常关注系统的吞吐量,吞吐量=代码运行时间/(代码运行时间+垃圾收集时间),多线程并行,作用于新生代,复制算法
-XX:MaxGCPauseMillis:设置最大垃圾收集停顿时间,可用把虚拟机在GC停顿的时间控制在MaxGCPauseMillis范围内,如果希望减少GC停顿时间可以将MaxGCPauseMillis设置的很小,但是会导致GC频繁,从而增加了GC的总时间,降低了吞吐量。所以需要根据实际情况设置该值。
-Xx:GCTimeRatio:设置吞吐量大小,它是一个0到100之间的整数,默认情况下他的取值是99,那么系统将花费不超过1/(1+n)的时间用于垃圾回收,也就是1/(1+99)=1%的时间。
另外还可以指定
-XX:+UseAdaptiveSizePolicy打开自适应模式,在这种模式下,新生代的大小、eden、from/to的比例,以及晋升老年代的对象年龄参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。
使用-XX:+UseParallelGC参数可以设置新生代使用这个并行回收器
Serial的老年代版本,单线程,作用于老年代
使用标记整理算法
一个是在JDK1.5及之前的版本中与Parallel Scavenge收集器搭配使用, 另一个就是作为CMS收集器的后备预案: 如果CMS出现Concurrent Mode Failure,则SerialOld将作为后备收集器。
Parallel Scavenge的老年代版本,多线程并行
使用标记整理算法
-XX:+UseParallelOldGc进行设置老年代使用该回收器
-XX:+ParallelGCThreads也可以设置垃圾收集时的线程数量。
作用于老年代,多线程并发 (重点学习, 后续详解)
使用标记清除算法
使用-XX:+UseConcMarkSweepGC进行设置老年代使用该回收器。
使用-XX:ConcGCThreads设置并发线程数量。
作用于堆,多线程并发 (重点学习, 后续详解)
整体还是基于标记清除算法
但是局部上是基于复制算法
CMS(Concurrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器。从名字就能知道其是给予标记-清除算法的。但是它比一般的标记-清除算法要复杂一些,分为以下4个阶段:
标记一下GC Roots能直接关联到的对象,会“Stop The World”。
GC Roots Tracing,可以和用户线程并发执行。
标记期间产生的对象存活的再次判断,修正对这些对象的标记,执行时间相对并发标记短,会“Stop The World”。
清除对象,可以和用户线程并发执行。
由于垃圾回收线程可以和用户线程同时运行,也就是说它是并发的,那么它会对CPU的资源非常敏感,CMS默认启动的回收线程数是(CPU数量+3)/ 4,当CPU<4个时,并发回收是垃圾收集线程就不会少于25%,而且随着CPU减少而增加,这样会影响用户线程的执行。而且由于它是基于标记-清除算法的,那么就无法避免空间碎片的产生。CMS收集器无法处理浮动垃圾(Floating Garbage),可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。
所谓浮动垃圾,在CMS并发清理阶段用户线程还在运行着,伴随程序运行自然还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只能留待下一次GC时再清理掉。
Garbage-First,号称最牛逼的垃圾收集器,面向服务端应用,在未来比较长的时间内代替CMS收集器,来看看它是怎样工作的:
分区
如果不算维护Remembered Set的操作,G1收集器的运作大致可以分为以下四步 (与CMS步骤相似):
标记GC Roots直接关联的对象,并让下一阶段用户程序运行时,能在正确可用的Region中创建新对象,这阶段需要STW,但耗时很短
从GC Roots开始对堆中对象进行可达性分析,找出存活对象,耗时较长,但是与用户程序并发进行(这期间创建的新对象分配在指定的Region中了)
修正在并发标记期间由于用户程序继续运行导致标记产生变动的那一部分标记记录,虚拟机把这段时间对象变化记录在线程Remembered Set Logs中,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set 中,这阶段需要STW,但是可并行执行。
先对各个Region回收按价值排序,根据用户所期望的GC停顿时间来制定回收计划。
结语
其实关于JVM远未结束, 继续写的话, 还有JVM性能调优配置说明 (过段时间写吧)、JVM垃圾回收器选用因素、JVM如何发起回收…