天天看点

Java堆与垃圾收集器(GC)

Java堆:

Java堆内存空间在虚拟机启动时创建,是Java虚拟机锁管理的最大内存区域;垃圾收集器的主要区域;它被所有线程共享。堆内存的唯一目的是存放对象实例。

Java堆空间分为老年代和新生代。老年代用于存储经过多次Minor GC后,任然存活的对象,或者是创建的大对象(新生代空间不足,会直接将大对象存放在老年代);新生代主要用于存储新创建的对象,新生代又分为Eden区、From Survivor区(也叫From区)、To Survivor区(也叫To区)。如下图:

Java堆与垃圾收集器(GC)

新创建的对象存储在新生代中的Eden区,eden区也是新生代的主要内存区;Eden区的对象经过一次GC后依然存活的对象会进入from区,from区经过一次GC后将存活的对象存入to区,to区经过一次GC后会将存活的对象存入from区。这里from区和to区不是固定的,而是会随着GC算法相互转化,from区可以为to区,to区可以为from区。严格的来说,都是from区经过一次GC后,将存活的对象存入to区。而from区和to区的对象经过若干次GC后(默认15次),如果依然存活,则会进入到老年代。而判断一个类是否死亡,需同时满足三个条件:

  •           (1)、该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例;
  •           (2)、加载该类的ClassLoader已经被回收
  •           (3)、该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

GC:

  • Minor GC:新生代GC,指发生在新生代的垃圾收集动作,所有的Minor GC都会触发全世界的暂停(stop-the-world),停止应用程序的线程,不过这个过程非常短暂。当堆中的Eden区空间不足时会出发monor GC
  • Major GC/Full GC:老年代GC,指发生在老年代的GC。老年代中空间不足时触发Major/Full GC

垃圾收集器:

  • 新生代:serial收集器、parNew收集器、parallelScavenage收集器
  • 老年代:CMS收集器、serialOld收集器、parallelOld收集器
  • 通用收集器:G1收集器,可用于新生代,也可用于老年代
Java堆与垃圾收集器(GC)

实现连接的收集器,表示可以设置新生代和老年代的垃圾收集器配合使用。

  • serial收集器:是Hotspot运行在Client模式下的默认新生代收集器,使用停止赋值算法。它是单线程、串行垃圾收集器,在进行垃圾收集工作时会暂停其他线程。可以使用 -XX:+UseSerialGC开启。特点是简单高效,在管理内存空间不大的情况下适合使用。
  • parNew收集器:是Serial的多线程版本,用多个线程进行GC,并行,其它工作线程暂停,关注缩短垃圾收集时间。除使用多线程GC外,其他参数、算法、规则与Serial完全相同。使用-XX:+UseParNewGC开启ParNew+Serial Old收集器组合收集内存;使用-XX:ParallelGCThreads来设置执行内存回收的线程数。
  • Parallel Scavenge 收集器:使用停止复制算法,关注CPU吞吐量。系统吞吐量=运行用户代码时间 / (运行用户代码时间+垃圾收集时间)。使用-XX:+UseParallelGC开启Parallel Scavenge+Serial Old收集器组合回收垃圾(这是在Server模式下的默认值);使用-XX:GCTimeRatio来设置用户执行时间占总时间的比例,默认99,即1%的时间用来进行垃圾回收。使用-XX:MaxGCPauseMillis设置GC的最大停顿时间(只对Parallel Scavenge有效);-XX:+UseAdaptiveSizePolicy可以进行动态控制,如自动调整Eden/Survivor比例,老年代对象年龄,新生代大小等,这个参数在ParNew下没有。
  • CMS(Concurrent Mark Sweep)收集器:是以获取最短垃圾收集停顿时间为目标的收集器,CMS收集器的关注点尽可能缩短垃圾收集时用户线程的停顿时间,停顿时间越短就越适合与用户交互的程序。使用标记清除算法,多线程,优点是并发收集(用户线程可以和GC线程同时工作),停顿小。使用-XX:+UseConcMarkSweepGC开启ParNew+CMS+Serial Old进行内存回收,优先使用ParNew+CMS,当用户线程内存不足时,采用备用方案Serial Old收集。
  • Serial Old收集器:单线程、串行收集器,使用标记整理(整理的方法是Sweep(清理)和Compact(压缩))算法,使用单线程进行GC,其它工作线程暂停。
  • Parallel Old收集器:多线程,并行收集器,使用标记整理(与Serial Old不同,这里是Summary(汇总)和Compact(压缩),汇总指将幸存的对象复制到预先准备好的区域,而不是像Sweep(清理)那样清理废弃的对象)算法。在Parallel Old执行时,仍然需要暂停其它线程。Parallel Old出现后,与Parallel Scavenge配合有很好的效果,充分体现Parallel Scavenge收集器吞吐量优先的效果。使用-XX:+UseParallelOldGC开关控制使用Parallel Scavenge +Parallel Old组合收集器进行收集。
  • G1收集器:JDK1.7出现,既可以回收新生代,也可以回收老年代。基于“标记—整理”算法,不会产生碎片空间,可以精确控制停顿时间。面向服务端应用的垃圾收集器,主要针对配备多核CPU及大容量内存的机器,以极高概率满足GC停顿时间的同时,还兼具高吞吐量的性能特征。

JDK8中默认使用组合是: Parallel Scavenge GC 、ParallelOld GC

JDK9默认是用G1为垃圾收集器

JDK14 弃用了: Parallel Scavenge GC 、Parallel OldGC

JDK14 移除了 CMS GC

常用垃圾收集器参数: 

Java堆与垃圾收集器(GC)

GC日志参数:

Java堆与垃圾收集器(GC)