Java垃圾收集算法

 由于垃圾收集算法的实现涉及大量的程序细节,而且每个平台的虚拟机操作内存的方法又各不相同,因此博客中不过多的讨论算法的实现,只是介绍几种算法的思想以及发展。

  相关阅读:

  1、深入理解java虚拟机之java内存区域

  2、深入理解java虚拟机之对象真的死了吗

  1、标记-清除算法

  标记清除算法分为“标记”和“清除”两个阶段,首先先标记出那些对象需要被回收,在标记完成后会对这些被标记了的对象进行回收;如下图:

  这种算法的优点在于不需要对对象进行移动操作,仅对不存活的对象进行操作,所以在对象存活率较高的情况下效率非常高,但是从上图模拟的结果来看对象被回收后,可用的内存并不是连续的,而是断断续续,造成大量的内存碎片。 存储对象时要求内存空间时连续的,所以虚拟机在给新的内存较大的对象分配空间时,有可能找不到足够大的连续的空闲的空间来存放,从而引发一次垃圾回收动作,实际上里面是有大量的空闲空间的,只是不连续而已。

  2、复制算法

  复制算法是将内存分为两块大小一样的区域,每次是使用其中的一块。当这块内存块用完了,就将这块内存中还存活的对象复制到另一块内存中,然后清空这块内存。这种算法在对象存活率较低的场景下效率很高,比如说新生代,只对整块内存区域的一半进行垃圾回收,在垃圾回收的过程也不会出现内存碎片的情况,不需要移动对象,只需要移动指针即可,实现简单,所以运行效率很高。运行效率是在建立在浪费空间的基础上的,这是典型的已空间换时间的方法,因为每次只能是使用北村的一半。算法示意图如下:

  

  现在商用的jvm中都采用了这种算法来回收新生代,因为新生代的对象基本上都是朝生夕死的,存活下来的对象约占10%左右,所以需要复制的对象比较少,采用这种算法效率比较高。hotspot版本的虚拟机将堆(heap)内存分为了新生代和老年代,其中新生代又分为内存较大的Eden区和两个较小的survivor区。当进行内存回收时,将eden区和survivor区的还存活的对象一次性地复制到另一个survivor空间上,最后将eden区和刚才使用过的survivor空间清理掉。hotspot虚拟机默认eden和survivor空间的大小比例为8:1,也就是每次新生代中可用内存空间为整个新生代空间的90%(80%+10%),只会浪费掉10%的空间。当然,98%的对象可回收只是一般场景下的数据,我们没有办法保证每次回收都只有不多于10%的对象存活,当survivor空间不够用时,需要依赖于其他内存(这里指的是老年代)进行分配的担保。

  3、标记-整理算法

  复制算法在对象存活率较高的情况下就要进行较多的对象复制操作,效率将会变低。更关键的是,如果你不需要浪费50%的空间,就需要有额外的空间进行分配担保,用以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种办法。

  根据老年代的特点,有人提出了标记-整理的算法,标记过程仍然与标记-清楚算法一样,但后续步骤不是直接将可回收对象清理掉,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存,算法示意图如下:

  4、分代收集算法

  分代收集算法将heap区域划分为新生代和老年代,新生代的空间比老年代的空间要小。新生代又分为了Eden和两个survivor空间,它们的比例为8:1:1。对象被创建时,内存的分配是在新生代的Eden区发生的,大对象直接在老年代分配内存,IBM的研究表明,Eden区98%的对象都是很快消亡的。

  为了提高gc效率,分代收集算法中新生代和老年代的gc是分开的,新生代发生的gc动作叫做minor gc 或 young gc,老年代发生的叫做major gc 或 full gc。

  minor gc 的触发条件:当创建新对象时Eden区剩余空间小于对象的内存大小时发生minor gc;

  major gc 触发条件:

  1、显式调用System.gc()方法;

  2、老年代空间不足;

  3、方法区空间不足;

  4、从新生代进入老年代的空间大于老年代空闲空间;

  Eden区对象的特点是生命周期短,存活率低,因此Eden区使用了复制算法来回收对象,上面也提到复制算法的特点是在存活率较低的情况下效率会高很多,因为需要复制的对象少。与一般的复制算法不同的是,一般的复制算法每次只能使用一半的空间,另一半则浪费掉了,Eden区的回收算法也叫做"停止-复制"算法,当Eden区空间已满时,触发Minor GC,清理掉无用的对象,然后将存活的对象复制到survivor1区(此时survivor0有存活对象,survivor1为空的),清理完成后survivor0为空白空间,survivor1有存活对象,然后将survivor0和survivor1空间的角色对象,下次触发Minor gc时重复上述过程。如果survivor1区剩余空间小于复制对象所需空间时,将对象分配到老年代中。每发生一次Minor gc时,存活下来的对象的年龄则会加1,达到一定的年龄后(默认为15)该对象就会进入到老年代中。

  老年代的对象基本是经过多次Minor gc后存活下来的,因此他们都是比较稳定的,存活率高,如果还是用复制算法显然是行不通的。所以老年代使用“标记-整理”算法来回收对象的,从而提高老年代回收效率。

  总的来说,分代收集算法并不是一种具体的算法,而是根据每个年龄代的特点,多种算法结合使用来提高垃圾回收效率。

  参考资料:《深入理解Java虚拟机》

Java垃圾收集算法1的更多相关文章

  1. JAVA 垃圾收集算法,垃圾收集器与内存分配策略(内容全面,解析简单易懂)

    垃圾收集器需要解决的三个问题: 1)哪些内存需要回收 2)什么时候回收 3)如何回收 背景:程序计数器,虚拟机栈,本地方法栈3个区域随线程而生,随线程而灭,在这几个区域内不需要过多的考虑回收的问题,因 ...

  2. JVM笔记3:Java垃圾收集算法与垃圾收集器

    当前商业虚拟机的垃圾收集都采用"分代收集"算法,即根据对象生命周期的不同,将内存划分几块,一般为新生代和老年代,不同的代根据其特点使用最合适的垃圾收集算法 一,标记-清除算法: 该 ...

  3. Java垃圾收集算法

    算法名称 过程 优缺点 1. 标记-清除算法 (Mark-Sweep) 分为两个阶段: 1.首先标记出所有需要回收的对象: 2.在标记完成后统一回收所有被标记的对象. 缺点: 1.效率问题:标记和清除 ...

  4. Java垃圾收集算法介绍

    垃圾回收器GC(Garbage Collection) 一.引用计数算法(Reference Counting) 介绍:给对象添加一个引用计数器,每当一个地方引用它时,数据器加1:当引用失效时,计数器 ...

  5. 【Java】JVM(二)、Java垃圾收集算法

    一.标记-清除算法 算法主要分为两个步骤 1. 标记: 遍历所有的 GC Roots, 然后标记所有可达对象为存活对象 2. 清除: 遍历堆中所有对象,然后将没有标记的对象清除. 存在不足: 1. 效 ...

  6. jvm系列(三):java GC算法 垃圾收集器

    GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...

  7. 深入理解Java虚拟机 - 垃圾收集算法与垃圾收集器

    1. 垃圾收集算法       JVM的垃圾收集算法在不同的JVM实现中有所不同,且在平时工作中一般不会深入到收集算法,因此只对算法做较为简单的介绍.       1.1 标记-清除算法        ...

  8. Java面试常考------------------------垃圾收集算法

    对于Java系学生而言,Java虚拟机中的垃圾收集算法是一个很重要的面试考点. 常用的垃圾收集算法主要可划分为以下三类: 1. 标记-清除算法 标记清除算法是一种比较简单的方法,直接标记内存中待回收的 ...

  9. Java GC算法 垃圾收集器

    GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为"GC",它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. ...

随机推荐

  1. 引爆炸弹——DFS&&联通块

    题目 链接 在一个$n \times m$方格地图上,某些方格上放置着炸弹.手动引爆一个炸弹以后,炸弹会把炸弹所在的行和列上的所有炸弹引爆,被引爆的炸弹又能引爆其他炸弹,这样连锁下去. 现在为了引爆地 ...

  2. url传参特殊字符问题(+、%、#等)

    这样的话,你传的大多数带特殊符号的参数,都能在后台拿到,但是, url中可能用到的特殊字符及在url中的经过编码后的值:(此表格借鉴) 字符   特殊字符的含义 URL编码 #   用来标志特定的文档 ...

  3. python-platform模块:平台相关属性

    import platform x=platform.machine() #返回平台架构 #AMD64 x=platform.node() #网络名称(主机名) #DESKTOP-KIK668C x= ...

  4. Codeforces Round #346 (Div. 2) E题 并查集找环

    E. New Reform Berland has n cities connected by m bidirectional roads. No road connects a city to it ...

  5. jQuery系列(十二):事件委托

    1.什么是事件委托 通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这 ...

  6. 如何利用新浪官方的短网址API接口实现T.cn短链接的压缩生成

    短网址的实现原理就是有一个数据表会配置文件将短网址和实际网址进行对应,当请求某个短网址时,程序跳转到对应的实际网址上去,从而实现网址的访问.目前国内最稳定最好用的是新浪T.cn短链接. 之前新浪提供了 ...

  7. 在linux写一个shell脚本用maven git自动更新代码并且打包部署

    服务器上必须安装了git maven jdk 并且配置好环境变量 实际服务器中可能运行着多个Java进程,所以重新部署的时候需要先停止原来的java进程,写一个按照名称杀死进程的脚本 kill.sh ...

  8. 微服务RESTful 接口设计规范

    1.RESTful发展背景及简介 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......).因此,必须有一种统一的机制,方便不同的前 ...

  9. LC 970. Powerful Integers

    Given two non-negative integers x and y, an integer is powerful if it is equal to x^i + y^j for some ...

  10. python3.6 列表推导式学习

    a=[i for i in range(1,10) if i%2==0]print(a)c=[(x,y) for x in range(5) if x%2==0 for y in range(5) i ...