垃圾回收算法及垃圾回收器

内存申请、对象衰老过程

一、内存申请过程

  1. JVM会试图为相关Java对象在Eden中初始化一块内存区域;
  2. 当Eden空间足够时,内存申请结束。否则到下一步;
  3. JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;
  4. Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;
  5. 当old区空间不够时,JVM会在old区进行major collection;
  6. 完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”Out of memory错误”;

基本的收集算法

  1. 复制算法

  2. 标记清除算法

  3. 标记整理算法

  4. 分代算法

    什么叫根对象?

    • q
    • q

    • 复制算法

    ​ 将堆内分成两个相同空间,从根(ThreadLocal的对象,静态对象)开始访问每一个关联的活跃对象,将空间A的活跃对象全部复制到空间B,然后一次性回收整个空间A。 因为只访问活跃对象,将所有活动对象复制走之后就清空整个空间,不用去访问死对象,所以遍历空间的成本较小,但需要巨大的复制成本和较多的内存。

    ​ 优点:只访问活跃对象,遍历快

    ​ 缺点:需要内存比较多,浪费一部分内存,不适合年老代

    有哪些阶段使用了复制算法?

    • Serial收集器-XX:+UseSerialGC

    • ParNew收集器-XX:+UseParNewGC

    • Parallel Scavenge收集器-XX:+UseParallelGC

    • 标记清除算法

    ​ 收集器先从根开始访问所有活跃对象,标记为活跃对象。然后再遍历一次整个内存区域,把所有没有标记活跃的对象进行回收处理。该算法遍历整个空间的成本较大暂停时间随空间大小线性增大,而且整理后堆里的碎片很多。

    ​ 优点:不浪费内存

    ​ 缺点:遍历2次,2次标记效率都不高,内存碎片多

    有哪些阶段使用了标记清除算法?

    • CMS(Concurrent Mark Sweep)收集器XX:+UseconcMarkSweepGC 标记,置换 不压缩

    • 标记整理算法

    ​ 综合了上述两者的做法和优点,先标记活跃对象,然后将其合并成较大的内存块。

    ​ 移动了活跃对象,回收后留下完整内存块。有哪些阶段使用了标记整理算法?

    • Serial Old收集器-XX:+UseSerialOldGC
    • arallel Old收集器-XX:+UseParallelOldGC

    • 分代收集算法

    ​ 现在比较常用的是分代收集(generational collection,也是SUN VM使用的,J2SE1.2之后引入),即将内存分为几个区域,将不同生命周期的对象放在不同区域里:young generation,tenured generation和permanet generation。绝大部分的objec被分配在young generation(生命周期短),并且大部分的object在这里die。当young generation满了之后,将引发minor collection(YGC)。在minor collection后存活的object会被移动到tenured generation(生命周期比较长)。最后,tenured generation满之后触发major collection。major collection(Full gc)会触发整个heap的回收,包括回收young generation。permanet generation区域比较稳定,主要存放classloader信息

    ​ 复制算法:young generation有eden、2个survivor 区域组成。其中一个survivor区域一直是空的,是eden区域和另一个survivor区域在下一次copy collection后活着的objecy的目的地。object在survivo区域被复制直到转移到tenured区。

垃圾收集器

  • Serial收集器-XX:+UseSerialGC 复制收集算法   

    ​ 单线程收集器,收集时会暂停所有工作线程(我们将这件事情称之为Stop The World,下称STW),使用复制收集算法,虚拟机运行在Client模式时的默认新生代收集器。

  • ParNew收集器-XX:+UseParNewGC 复制收集算法 多线程执行   

    ​ ParNew收集器就是Serial的多线程版本,除了使用多条收集线程外,其余行为包括算法、STW、对象分配规则、回收策略等都与Serial收集器一摸一样。对应的这种收集器是虚拟机运行在Server模式的默认新生代收集器,在单CPU的环境中,ParNew收集器并不会比Serial收集器有更好的效果。

  • Parallel Scavenge收集器-XX:+UseParallelGC 复制算法,吞吐量最大化   

    ​ Parallel Scavenge收集器(下称PS收集器)也是一个多线程收集器,也是使用复制算法,但它的对象分配规则与回收策略都与ParNew收集器有所不同,它是以吞吐量最大化(即GC时间占总运行时间最小)为目标的收集器实现,它允许较长时间的STW换取总吞吐量最大化。

  • Serial Old收集器-XX:+UseSerialOldGC 标记整理算法

    Serial Old是单线程收集器,使用标记-整理算法,是老年代的收集器,上面三种都是使用在新生代收集器。

  • Parallel Old收集器-XX:+UseParallelOldGC 标记整理算法多线程执行   

    ​ 老年代版本吞吐量优先收集器,使用多线程和标记-整理算法,JVM 1.6提供,在此之前,新生代使用了PS收集器的话,老年代除Serial Old外别无选择,因为PS无法与CMS收集器配合工作。

  • CMS(Concurrent Mark Sweep)收集器XX:+UseconcMarkSweepGC 标记,置换 不压缩 算法

    ​ 压缩需要加参数-XX:CMSFullGCsBeforeCompaction(多少次FullGC后压缩内存) 或者-XX+UseCMSCompactAtFullCollection(CMS后压缩内存)
    CMS收集器使用的是标记-清除算法,也就是说它在运行期间会产生空间碎片,所以虚拟机提供了参数开启CMS收集结束后再进行一次内存压缩。
    CMS垃圾收集器的回收过程:

猜你喜欢

转载自blog.csdn.net/wf_feng/article/details/82225602