【JVM】第三章_1 垃圾收集器

第三章_1 垃圾收集器

一、概述

垃圾收集GC,这项技术当做java语言的伴生产物。

 

有三个问题需要回答:

1、哪些内存需要回收?

1)基于线程隔离的区域(操作数栈、本地变量表这些)不需要回收,因为它的生命周期是基于线程存在的,方法或线程结束,内存自然也跟着回收

2)堆空间需要进行回收。堆空间又分为堆区和非堆区,而堆区又分为新生代(朝生夕灭)和老年代。这些空间都需要进行回收。

 

2、什么时候回收?

1)当Eden区没有足够的空间进行分配时,触发新生代回收。

2)当Old区空间达到一定的界限时触发Full GC

3)方法区达到一定的界限时,触发GC

 

3、如何回收?

收回算法,分代回收原则。

 

 

二、如果判断对象是否已死

1、引用计数法

给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1,当引用失效时就减1.任何时候计数器的值为0,就说明对象已死。

这个有个缺点,不能解决对象之间相互循环引用的问题。

objA.instance=objB

objB.instance=objA

 

2、枚举根节点,做可达性分析

凡事根节点不可达的对象,都可以进行收回。但不一定马上进行回收,具体得看不同GC的实现。

GC Roots包括哪些:

1)虚拟机栈(本地变量表)中引用的对象。

2)方法区静态属性引用的对象

3)方法区常量引用的对象

4)本地方法栈中 JNI(native方法)引用的对象

 

3、对象的死亡过程

两次标记,才能真正的宣告死亡

1)当进行完可达性分析之后,发现对象没有GC Roots的引用链,则进行第一次标记。

如果该对象对象覆盖了 finalize()方法,则把对象放到F-Queue队列中,并开启一个低优先级的线程去执行 F-Queue.在这个阶段如果发现有对象再次被引用,则成功拯救自己。

2)对F-Queue进行标记,没有成功拯救自己的对象,都会宣告死亡。

 

 

三、垃圾收集算法

 

  • 新生代

1、复制算法

Survivor区,一块叫From,一块叫To,对象存在Eden和From块。当进行GC时,Eden存活的对象全移到To块,(也得看TO空间的大小是否够,不够用时进行分配担保,进入old区)

而From中,存活的对象按年龄值确定去向,当达到一定值(年龄阈值,通过-XX:MaxTenuringThreshold可设置)的对象会移到年老代中,没有达到值的复制到To区,经过GC后,Eden和From被清空。 

之后,From和To交换角色,新的From即为原来的To块,新的To块即为原来的From块,且新的To块中对象年龄加1.

 

Eden和survivor内存大小比例为8:1

 

优点:

不用进行内存整理,直接进行复制,然后直接清除,实现简单高效。

缺点:

浪费点空间。因为S0或S1肯定有一个是空的。

对于朝生夕死的对象来说,效率还好。但对于存活率较高的情况下,如果频繁的来回复制效率也不会太高。所以复制算法比较适合新生代的垃圾收集。

 

  • 老年代

2、标记-清除算法

标记和清除是两个步骤,当前是先标记后进行清除。

标记刚才讲过就是两次标记的过程,但这种算法有它的不足之处:

1、标记和清除的效率都不高

2、空间利用率问题,标记清除之后会产生大量的不连续内存碎片。可能导致以后分配大对象时发现没有连续的空间可用,不得不进行Full GC

 

3、标记-整理算法

标记:过程不用再说,和前面的一样都是两次标记的过程。

整理:让所有的存活的对象都向一端移动,然后清理掉端边界以外的内存。

 

优点:

标记-整理完之后,空间内不会有非连续的内存碎片。

 

  • 分代收集法

4、分代收集法的核心思想

目前商业的GC收集器都采用的是分代收集的思想。

这个比较简单就是把堆划分为新生代和老年代,根据新生代和老年代的特点,使用不同的垃圾回收算法。

新生代:复制法

老年代:标记-清除法、标记-整理法

 

四、垃圾收集器

在介绍垃圾收集器之前先说一下怎么评价一款垃圾收集器的性能:

1)最小的停顿时间(stop the world)

在枚举根节点期间,要必免我在这分析,那边对象的引用又发生了变化,这种分析结果的准确性得不到保障。所以在进行可达性分析的时候,必须停顿所有的java执行线程。

2)最大的吞量

CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码时间 / (运行用户代码时间+垃圾收集时间)

根据这个公式可以看出,垃圾收集时间越小,吞吐量越高。性能越好。

 

 

1、Serial 收集器(现在很少见了)

单线程收集器、新生代、停顿时间长、复制算法

单线程收集:它进行垃圾收集的时,必须暂停其化所有的工作线程,直到它收集结束。

常见的组合:serial + serial old

 

2、ParNew 收集器

Serial收集器的多线程版本(并行收集)、新生代、复制算法

它时行收集的时候同样必须暂停所有的工作线程,直到它收集结束。不同的是Serial是只有一个线程进行收集,ParNew呢是多个线程进行收集。

常见的组合:ParNew + CMS + Serial Old(备用)

 

3、Parallel Scavenge 收集器

多线程并行收集、新生代、复制算法。这个同ParNew没啥大区别。它的特点在于:

1)它关注的是吞吐量,也称“吞吐量优先”收集器

2)自适应调节策略。只需要设置吞吐量和停顿时间参数,其它的交给收集器去做。

 

 

 

4、Serial Old 收集器(也很少用到了)

Serial 收集器的老年代版本。单线程、标记-整理算法

常见的搭配方案:

Serial + Serial Old

ParNew + CMS + Serial Old

 

5、Parallel Old 收集器(jdk1.6中才开始提供)

Parallel 收集器的老年代版本、多线程并行、标记-整理算法

搭配方案:

Parallel + parallel Old

 

6、CMS收集器

老年代、并发收集器(并发指用户线程与垃圾收集线程可同时执行。但并不表示可以不用stop the world 因为STW是在标记的阶段进行的。同样也是需要STW的。只是它追求的是最小的停顿时间)

标记-清除算法

特点:并发收集,低停顿

1)并发收集器

2)以获取最短回收停顿时间为目标的收集器

 

整个过程:

1)初始标记(需要stop the world)

标记GC Roots能关联到的对象

2)并发标记

GC Roots Tracing过程

3)重复标记(需要stop the world)

修正在并发标记阶段因用户线程继续运行导致的对象变化,进行重新标记

4)并发清除

 

缺点:

1)对cpu资源敏感

2)无法处理浮动垃圾

因是它是一边用户线程运行,一边垃圾收集,所以不能保障一次性收集干净,如果在运行期间预留的内存无法满足程序的需要,就会出现“Concurrent Mode Failure”失败,从而触发 Serial Old备用方案

3)基于标记-清除算法,会有大量的空间碎片。将会对大对象分配带来麻烦。不得不提交进行Full GC或者内存碎片合并整理过程

 

7、G1 收集器

新生代和老年代收集器、多线程并发收集、标记-整理算法

jdk1.7中开始提供,jdk1.8中比较成熟了,jdk1.9中是默认的收集器了。

处理大内存大于等于6G,还可以停顿时间非常的小。0.5秒以内

 

 

它把新生代和老年代当作是一个逻辑上的概念了,不再进行区分。

1)内存块(Region)

在G1算法中,采用了另外一种完全不同的方式组织堆内存,堆内存被划分为多个大小相等的内存块(Region),每个Region是逻辑连续的一段内存,结构如下:

说一下Humongous,这表示这些Region存储的是巨型对象(humongous object,H-obj),当新建对象大小超过Region大小一半时,直接在新的一个或多个连续Region中分配,并标记为H。

 

2)SATB(存活对象快照)

通过Roots Tracing得到的,GC开始时候存活对象的快照。这个干什么用呢,就是帮助对象回收。

 

3)Rset 记录Region之间的对象相互引用关系

记录谁引用了我的对象,避免全堆扫描。在GC根节点枚举范围中加入Rset即可保证不对全堆扫描也不会有遗漏。

 

4)YoungGC这一块没有变化:

 

5)MixedGC

 

global concurrent marking 全局并发标记,这个跟 CMS的标记阶段很像

 

 

当堆的占有率达到45%时,并发Mixed GC 并发标记,不代表会进行MixedGC,

还有一个参数控制着是进行YGC还是进行MixedGC

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值