JVM中内存回收深入分析,各种垃圾收集器

时间:2022-04-11 09:17:51

JVM启动有两种模式,client和server

一般JVM启动时会根据主机情况分析选择采用那种模式启动

JVM中内存回收深入分析,各种垃圾收集器可发现是server模式

JVM中尤其需要关注的就是HEAP堆区

堆区分为新生代和老年代

新生代分为eden,s0,s1

老年代就Old

什么时候出发垃圾回收呢?

当新对象在eden区分配失败时就会触发一次YGC,即新生代的垃圾回收,eden区中的存活对象进入s0,s0若放不下,进入OLD,再扫描S1区,存活次数超过阀值的进入OLD,否则进入S0,之后,s0和s1交换。

当老年代放不下时就出发FGC。

内存的回收策略有

串行/并行

串行即单线程负责垃圾回收,不适合多CPU,耗时长

并行即多线程垃圾回收,适合多CPU,效率高

stop the world/并发

stop the world,JVM里的应用线程会挂起,只有垃圾回收线程在运行,回收的干净,因为没有任何应用线程在垃圾回收时再次产生垃圾

并发,垃圾回收时,应用线程也在运行,回收不干净,因为应用线程在垃圾回收时也可能产生新的垃圾

压缩/非压缩

垃圾回收后清理碎片,压缩空间

新生代串行垃圾收集器

采用stop the world的策略

老年代串行垃圾收集器

MARK-->标记存活对象,SWEEP-->回收垃圾,COMPACT-->压缩空间碎片

jmap -heap pid查看堆区使用情况

JVM中内存回收深入分析,各种垃圾收集器

jstat -gcutil pid time查看各个区的实时使用情况

JVM中内存回收深入分析,各种垃圾收集器

可以清楚的看到YGC的发生情况

收集算法是内存回收的方法论,收集器是内存回收的具体实现,主要的收集器有如下几种:

serial收集器:

复制收集算法,在垃圾回收时,必须暂停其它的所用应用线程,回收策略为stop the world,单线程的,serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择,简单而高效,对于单个CPU的环境,没有线程交互的开销,专心垃圾回收,而且一般桌面应用中新生代也不会很大,回收暂停时间很短。针对新生代的收集器。

ParNew收集器:

是serial收集器的多线程版本,其它与serial收集器完全一样。是运行在server模式下首选新生代收集器,有一个很重要的原因是,除了serial收集器,目前只有它能与CMS收集器配合工作。

-XX:+UseConcMarkSweepGC设置老年代为并发收集,-XX:UseParNewGC设置年轻代为并发收集

Parallel Scavenge收集器:

新生代收集器,采用复制算法,可控制垃圾回收暂停时间以及吞吐量大小,-XX:MaxGCPauseMillis(毫秒),-XX:GCTimeRatio,它是 以吞吐量最大化(即GC时间占总运行时间最小)为目标的收集器实现,它允许较长时间的STW(stop the world)换取总吞吐量最大化。

Serial Old收集器:

标记整理算法,是Serial收集器的老年代版本

Parallel Old收集器:

Parallel Scavenge收集器的老年代版本,标记整理算法

CMS收集器:

是一种以获取最短回收停顿时间为目标的收集器,标记清除算法,

初始标记-->并发标记-->重新标记-->并发清除

其中初始标记和重新标记仍然会发生stop the world,初始标记是标记一下GC ROOTS能直接关联到的对象,速度很快,并发标记就是GC ROOTS TRACING的过程,而重新标记是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象标记记录。

整个过程中,耗时最长的并发标记和并发清除可以与应用线程并发进行。

G1收集器:

标记整理算法,不会产生碎片,会整理碎片,空间连续,

JVM中内存回收深入分析,各种垃圾收集器

该图是hotspot JVM 1.6的垃圾收集器选择的配合使用情况。

JVM中内存回收深入分析,各种垃圾收集器

上图是老年代的一次GC。