JVM随笔-垃圾回收
感觉JVM就是记的比较多,明白了概念就记。想明白细节原理,怕是要看源码(c/c++编写的)
垃圾收集
标记清除(老年)
标记阶段:通过可达性分析的算法,对可达的对象进行标记
清楚阶段:清楚标记阶段没有被标记的对象
标记清除有个弊端就是导致内存碎片
复制(新生)
eden取得对象复制到survivor区域,在survovor的对象,达到一定年龄,会进入老年代,其他的会从from(s0/s1) 复制到to(s0/s1)
复制算法解决的内存碎片的问题
标记压缩(老年)
首先对内存进行标记,然后进行清除,清除过程中,对存活的对象压缩到内存的一段端
标记压缩能够解决内存碎片问题
分代
按照对象的生命周期长短,把堆空间分为新生代和老年代,新生代的对象达到一定的年龄(默认15,一次回收年龄+1),会进入老年代。对不同年代的内存使用不同放入回收算法。
分区
把堆空间分成连续不同的小区间,每个小区间独立使用,独立回收。G1收集器就是使用分区算法。
垃圾收集器
串行收集器
新生代串行回收期是一个古老的回收器,使用单线程(复制算法)进行来回收,同时,他是一个独占式的垃圾回收器。在进行垃圾回收的时候,会STW(stop the world)操作,这个时候,整个应用程序会出现停顿。但是,进行垃圾回收前,会先运行到一个安全点(safepoint),或者安全区域(safe region)后,才会进行垃圾回收。
老年代串行回收器使用的是标记压缩的算法,一旦老年代串行回收器启动,应用程序可能会停顿较长的时候(老年代回收时间较长)。
串行回收器是一个成熟且经过长时间生产环境考验的极为高速的收集器。在CPU处理器等硬件平台不是特别好的场合,性能表现可以超过并行回收器和并发回收器。
并行收集器
新生代ParNew回收器,它是简单的将串行的回收器多线程化。在并发能力较强的CPU上,产生的停顿时间比串行回收器短。但是在CPU能力弱的情况下,串行的停顿的时候有可能比并行的长。
新生代ParallelGC回收器(独占,复制算法)是一个关注吞吐量的回收器。和新生代ParNew回收器不同的是,他可以通过设置参数,支持自适应GC调节策略。他会自动调节新生代大小、eden和survior的比例、晋升老年代的年龄,达到堆大小、吞吐量和停顿时间之间的平衡点。还可以设置参数,设置最大垃圾收集停顿的时间,设置吞吐量的大小。
吞吐量 = 运行用户代码时间 / ( 运行用户代码时间 + 垃圾收集时间 )
期望停顿的时间和吞吐量的大小是一对矛盾的设置,需要找到一个平衡点。
- 老年代ParallelOldGC回收器(独占,标记压缩法),他一般和新生代ParallelGC回收器搭配使用。
CMS收集器
- CMS的全称是Concurrent Mark Sweep,意思其实就是并发标记清除。CMS是一个基于标记清除算法的收集器。
总体上来说CMS收集器不是独占是的。他的工作流程包括:初始标记(独占,串行)、并发标记、预清除、重新标记(独占,并发)、并发清理、并发重置等。
新生代GC后,老年代又GC,这样的话,停顿的时候会很长。为了避免较长的停顿时间,预清理的时候,会故意等待一次新生代GC的发生,同时根据历史数据,预测下次发生新生代GC的时间,重新标记一般会 发生在预测的下次新生代GC时间和本次GC时间的中间。
CMS默认启动的并发线程数是(ParallelGCThread+3)/4
CMS不会等待内存饱和的时候才进行内存回收,在内存到达某个阈值的时候,CMS才会进行内存回收,这个阈值默认值是68。同时,可以通过参数自己设定。在老年代占用内存较多的时候,可以考虑把这个阈值适当调高。
CMS的一个基于标记清除算法的收集器。所以会存在内存碎片的问题。所以,CMS会在回收进行到一定的次数的时候进行一次压缩操作。可以通过参数设定指定的次数。
CMS能够对Pern区进行回收。主要是对Class数据进行回收。可以通过设置参数使用CMS回收器进行对Pern区进行垃圾回收。
G1收集器
G1收集器的全称是Garbage First Garbage Collector。这个垃圾回收器会优先对垃圾比较多的区域进行垃圾回收。在JDK1.7中正式使用。目标是取代CMS。
G1垃圾回收器,仍然属于分代,因为他还是区分新生代和老年代。但是从堆结构上说,他不要求eden、新生代、老年代都连接,使用了分区的算法。
- G1回收器进行垃圾收集的过程总体上分为:新生代GC、并发标记周期(有回收的操作)、混合收集、Full GC(可能)。
理解垃圾收集总体的过程很重要。这有助于对G1的总体理解。
- 新生代GC:eden区域被占满,就会触发新生代GC。eden生存数据,from区生存的数据,会复制到to区。同时,年龄条件满足的新生代数据,会晋升为老年代。一个新生代GC下来,至少剩下一个survior区(eden和之前survior存活数据保存复制的地方)。
并发标记周期:分为6个阶段,由浅入深的对堆内存进行标记。
1.初始标记:独占,伴随着新生代GC,标记新生代可达对象
2.根区域扫描:新生代GC下来至少存活一个survior区,标记由survior区可达的老年代区域
3.并发标记:标记整个整个堆的存活对象
4.重新标记:独占,由于并发标记是并发的,可能存在错误,因此重新修正,补充标记
5.独占清理:独占,标记可供混合回收(下一个大阶段)的区域(不是标记对象,是标记区域)
6.并发清理:清除完全空闲(不包含存活对象)的区域。混合回收:在并发标记周期有部分对象被回收,但是回收的比例还是较低的。并发标记周期之后,已经确定了哪些区域垃圾较多,混合回收会优先对这些区域进行回收。混合回收了足够多的内存之后,会触发一次新生代GC,然后又会进行一次并发标记周期,再到混合回收,如此循环。
Full GC:在特别繁忙,内存不足的情况下,进行一次Full GC。