什么是GC垃圾回收呢。日常生活中我们去餐厅吃饭吃完饭,吃完饭走了餐具不用管,服务员在把餐具拿走,这是一种方式,服务员怎么知道他要来把餐具拿走呢,因为你走了,这个位置空了。服务员什么时候拿走餐具很重要,第一你没吃完,不会回收吧,第二很多人吃饭,你在里面,他也不一定回收吧,他会找一个合适的时机,一次性回收很多吧。

第二种方法:自己吃完饭把餐具带到回收的地方吧。

哪一种方式更好呢?

第一种方式自己也就是使用者不用管,服务员找一个合适的时机把垃圾回收了。

第二种自己去吧垃圾倒了。

在java中GC垃圾回收用的是第一种方式,系统找一个合适的时机把垃圾回收掉,我们不用手动去干预。这也是C#使用的垃圾回收机制。开发员人员只关心内存申请,不关心内存释放的问题

下面我们看一看垃圾回收GC回收算法。

1.1. 引用计数法

引用计数法是一种古老的垃圾收集方法,引用计数器实现很简单,对于一个对象A,有任何一个对象引用了A,那么A的计数器+1,引用失效时,A的计数器-1。当A的引用计数器是0的时候。那么A对象就不能被使用了。

引用计数法实现很简单就是额外的为每一个对象搞一个计数器,但是也有缺点:

1.引入计数器是解决一个问题又附加的引入一个问题。因为每次加减操作,可能影响系统性能。

2.无法处理循环引用问题,因此java的垃圾回收器中,没有使用这种算法。

下面举一个简单的例子:A对象和B对象,对象A中有B的引用,对象B中有A的引用。此时A和B两个对象的计数器都不是0,但在使用中没有其他对象引用A和B,说白了,A和B应该是被回收的对象,但是他们之间相互引用。计数器不为0,系统没有这种探针检测到循环引用,从而无法垃圾回收,引发内存泄露。

解释一个可达对象,不可达对象。

可达对象:通过根节点进行引用搜索,最终可以到达的对象。

不可达对象:通过根节点进行引用搜索,最终没有被引用的对象。

不可达的对象出现循环引用,它的引用计数器都不是0如下图所示:

1.2. 标记清除法

标记清除算法将垃圾的回收两阶段进行:标记阶段和清除阶段。

在标记阶段,顾名思义,就是从根节点开始标记可到达的对象。没有被标记的对象也就是没有被引用的对象那个就是垃圾对象。在第二个阶段也就是清除阶段,清除所有没有被标记的对象。标记清除算法。可能会产生空间的碎片,这也是这个算法的最大的问题。

如下图所示,使用标记清除算法对一块连续的内存空间进行回收,从根节点开始,所有的引用关系对象被标记为存活对象,

不可到达的对象被标记为垃圾对象,在清除阶段回收所有不可到达的对象,也就是没有被引用的对象。

如上图所示,回收后的空间是不连续的。在对象的堆空间分配中,大对象的内存分配,不连续的内存空间的效率低于连续的空间。这也是该算法的最大缺点。

标记阶段通过根节点查找所有可达对象,清除节点清除所有的不可达对象。完成系统的垃圾回收。

1.3. 复制算法

复制算法的原理:将分配的内存空间分为2块,每次只是用1块,在垃圾回收呢时,讲正在使用的内存中的存活对象复制到没有被使用的内存的一块,完成之后,清除正在使用的内存块中的所有对象,然后两个内存块交换,以此完成垃圾回收。

如果系统中的垃圾对象有很多,存活对象比较少,复制算法的优势就体现出来了。由于对象是在垃圾回收过程中统一被复制到新的内存空间,所以复制算法可以确保新的内存空间是没有碎片的。但是缺点就是,把内存分为了2块,不能充分的利用内存。

如下图所示:A、B两块相同的内存,A在进行垃圾回收的时候,讲存货的对象复制到B的空间,B的空间在复制后是连续的。复制完成之后,清除A。把B设置为当前使用的空间。

在java的新生代串行垃圾回收中,使用了复制算法,新生代之前的章节也讲过分为eden区域,from、to三个部分,之前也说过from、to是相等的可以替换的两个空间、地位相等、角色相等。from、to空间也被称之为survivor空间,英文解释为幸存者,用来存放没有被回收的对象,如下图所示。

新生代:堆空间中的年轻人,对象刚刚创建或者经历的垃圾回收次数不多的对象。

老年代:堆空间中的老年人,老年对象指经历了很多次垃圾回收亦然存活的对象,(看来大部分老年人存贮内存挺高的对象)。

在垃圾回收的过程中,eden空间存活的对象被复制到survivor空间,假如我们正在使用from空间,因此den空间存活的对象被复制到to空间。如果to空间内存满了,则对象直接进入老年代,可参考虚拟机参数设置的章节参考实例。此时eden空间和from空间剩余的对象就是垃圾对象,直接清空,to空间存放的就是存活的对象,这种改进之后的算法,保证了空间的连续性,这点很重要,又避免了大量的空间的浪费,因为这些空间是可以手动分配的。参考之前的章节。上图显示了复制算法的时机回收过程。

复制算法比较适合新生代,因为新生代垃圾对象一般比存活对象要多,这块区域,朝生夕死足矣。如果这个地方的对象存活就可能是常住内存的对象了。

1.4. 标记压缩法

上面也说了 压缩算法的使用前提是存活对象少、垃圾对象多的情况下使用。这种情况经常发生在新生代,在老年到就不合适了,因为老年代大部分都是存活对象,如果要使用复制算法,复制的成本很高,所以老年代使用的是其他的算法,老年人比较特殊嘛。

标记压缩算法是在标记清除算法基础之上优化了,标记压缩算法也是从根节点开始,对对象的可达性做一次扫描标记,之后不是直接清除未标记的对象,而是将所有的存活对象压缩到内存的一端,之后,清除边界外的所有空间,这样做的好处是避免了内存的不连续性,不需要内存设置两块相同的内存进行复制交换。所以压缩标记算法的性价比好啊。

标记压缩算法如下图所示完成垃圾回收。

标记压缩算法其实就是在标记清除算法完成之后,进行一次随便整理。所以称之为标记压缩算法。

1.5. 分区算法

上面说的都是出来堆空间的算法,对于栈是如何处理的呢。分区算法是将整个堆空间分成连续的不同的小区间,如下图所示。每一个小区间都是独立使用,独立回收,这样设计可以控制一次回收多少个区间。不回去全扫描。

一般来说在相同的条件下,堆空间越大,一次垃圾GC回收所需要的时间就越长,那么引起的副作用就是停顿时间越长,就是假死需要等待的时间就越长,使用分区算法的好处就是,合理的回收区间,不是扫描整个堆空间,从而减少一次GC产生的停顿。跟餐厅收餐具一样一样,分房间去收餐具,不是每次都按照顺序收餐具。

GC垃圾回收算法的更多相关文章

  1. Java GC 垃圾回收算法 内存分配

    垃圾回收(Garbage Collection, GC)是Java不同于c与c++的重要特性之一. 他帮助Java自动清空堆中不再使用的对象. 由于不需要手动释放内存,程序员在编程中也可以减少犯错的机 ...

  2. gc垃圾回收算法原理

    目录 三色标记法 标记-清扫(Mark And Sweep)算法 标记-清扫(Mark And Sweep)算法存在什么问题? 三色并发标记法 gc和用户逻辑如何并行操作? 进程新生成对象的时候,GC ...

  3. 6.GC垃圾回收算法和垃圾收集器的关系

    JAVAGC垃圾回收机制和常见垃圾回收算法 推荐博客:JVM垃圾回收机制和常见垃圾回收算法 JVM的内存结构.垃圾回收算法

  4. GC: 垃圾回收算法

    标记-清除算法标记-清除(Mark-Sweep)算法是最基础的算法,就如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象.之所以说 ...

  5. JVM中的垃圾回收算法GC

    GC是分代收集算法:因为Young区,需要回收垃圾对象的次数操作频繁:Old区次数上较少收集:基本不动Perm区.每个区特点不一样,所以就没有通用的最好算法,只有合适的算法. GC的4大算法 1.引用 ...

  6. 小师妹学JVM之:GC的垃圾回收算法

    目录 简介 对象的生命周期 垃圾回收算法 Mark and sweep Concurrent mark sweep (CMS) Serial garbage collection Parallel g ...

  7. 【C# .Net GC】垃圾回收算法 应用程序线程运行时,

    触发垃圾回收算法的条件 触发垃圾回收的条件 当满足以下条件之一时将发生垃圾回收: 操作系统报告低内存请看(将触发第2代垃圾回收). 这是通过 OS 的内存不足通知或主机指示的内存不足检测出来. 由托管 ...

  8. A6. JVM 垃圾回收算法(GC 算法)

    [概述] 常见的垃圾回收算法有:标记-清除算法.复制算法.标记-整理算法.分代收集算法. [标记-清除算法] 标记-清除算法是最基础的收集算法,如同它的名字一样,算法分为 “标记” 和 “清除” 两个 ...

  9. 深入理解java虚拟机【垃圾回收算法】

    Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...

随机推荐

  1. [SCOI2014]方伯伯的玉米田

    Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...

  2. [SDOI2008]Sue的小球

    题目描述 Sue和Sandy最近迷上了一个电脑游戏,这个游戏的故事发在美丽神秘并且充满刺激的大海上,Sue有一支轻便小巧的小船.然而,Sue的目标并不是当一个海盗,而是要收集空中漂浮的彩蛋,Sue有一 ...

  3. [JLOI2015]装备购买

    题目描述 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 <= j < ...

  4. 计蒜客NOIP模拟赛4 D2T1 鬼脚图

    鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合. 下图就是一张鬼脚图,其包含若干条竖线和若干条横线.请注意,横线只能水平连接相邻的两条竖线, ...

  5. ●洛谷P1083 借教室

    题链: https://www.luogu.org/problemnew/show/P1083题解: 二分,差分 显然具有二分性: 如果只考虑1~p个人,就会在某一天无法满足, 那么显然只考虑1~[p ...

  6. 洛谷mNOIP模拟赛Day1-分组

    传送门 首先是贪心的思路 从后向前选,能多选就多选, 理由:数字越少肯定越优,同时间隔尽量向前推,字典序尽量小 对于K==1,枚举1~512直接判断 对于K==2,需要用镜像并查集,来刻画" ...

  7. 【USACO11NOV】牛的阵容Cow Lineup 尺取法+哈希

    题目描述 Farmer John has hired a professional photographer to take a picture of some of his cows. Since ...

  8. Yii2.0源码阅读-behavior的实现原理

    Yii2.0中的一个思想就是组件化的思想,所以.大多数的类都直接或间接的继承自yii\base\Component,而组件的三大功能:属性.事件.行为. 行为的目的是为了方便的扩展一个类的功能,而不需 ...

  9. Linux 查看系统硬件信息汇总 (部份实例详解Centoso为例)

    1.cpu #lscpu命令,查看的是cpu的统计信息.(部分旧版本不支持) Disk /dev/sda: bytes heads, sectors/track, cylinders Units = ...

  10. JavaScript正则表达式模式匹配(4)——使用exec返回数组、捕获性分组和非捕获性分组、嵌套分组

    使用exec返回数组 var pattern=/^[a-z]+\s[0-9]{4}$/; var str='google 2012'; alert(pattern.exec(str)); //返回一个 ...