我们都知道java语言与C语言最大的区别就是内存自动回收,那么JVM是怎么控制内存回收的,这篇文章将介绍JVM垃圾回收的几种算法,从而了解内存回收的基本原理。

stop the world

在介绍垃圾回收算法之前,我们需要先了解一个词“stop the world”,stop the world会在执行某一个垃圾回收算法的时候产生,JVM为了执行垃圾回收,会暂时java应用程序的执行,等垃圾回收完成后,再继续运行。如果你使用JMeter测试过java程序,你可能会发现在测试过程中,java程序有不规则的停顿现象,其实这就是“stop the world”,停顿的时候JVM是在做垃圾回收。所以尽可能减少stop the world的时间,就是我们优化JVM的主要目标。接下来我们看一下目前有哪些常见垃圾回收的算法。

引用计数法

引用计数法顾名思义,就是对一个对象被引用的次数进行计数,当增加一个引用计数就加1,减少一个引用计数就减1。

上图表示3个Teacher的引用指向堆中的Teacher对象,那么Teacher对象的引用计数就是3,以此类推Student对象的引用计数就是2。

上图表示Teacher对象的引用减少为2,Student对象的引用减少为0(减少的原因是该引用指向了null,例如teacher3=null),按照引用计数算法,Student对象的内存空间将被回收掉。

引用计数算法原理非常简单,是最原始的回收算法,但是java中没有使用这种算法,原因有2。1是频繁的计数影响性能,2是它无法处理循环引用的问题。

例如Teacher对象中引用了Student对象,Student对象中又引用了Teacher对象,这种情况下,对象将永远无法被回收。

标记清除

标记清除算法,它是很多垃圾回收算法的基础,简单来说有两个步骤:标记、清除。

标记:遍历所有的GC Roots,并将从GC Roots可达的对象设置为存活对象;

清除:遍历堆中的所有对象,将没有被标记可达的对象清除;

注意上图灰色的对象,因为从GC Root遍历不到它们(尽管它们本身有引用关系,但从GC Root无法遍历到它们),因此它们没有被标记为存活对象,在清除过程中将会被回收。

这里需要注意的是标记清除算法执行过程中,会产生“stop the world”,让java程序暂停等待以保证在标记清除的过程中,不会有新的对象产生。为什么必须暂停java程序呢?举个例子,如果在标记过程完成后,又新产生了一个对象,而该对象已经错过了标记期,那么在接下来的清除流程中,这个新产生的对象因为未被标记,所以将被视为不可达对象而被清除,这样程序就会出错,因此标记清除算法在执行时,java程序将被暂停,产生“stop the world”。

接下来我们总结一下标记清除算法:

1、因为涉及大量的内存遍历工作,所以执行性能较低,这也会导致“stop the world”时间较长,java程序吞吐量降低;

2、我们注意到对象被清除之后,被清除的对象留下内存的空缺位置,造成内存不连续,空间浪费。

接下来我们看一下其他算法能不能改善这些问题?

标记压缩

标记压缩算法你可能已经想到了,它就是在标记清除算法的基础上,增加了压缩过程。

在进行完标记清除之后,对内存空间进行压缩,节省内存空间,解决了标记清除算法内存不连续的问题。

注意标记压缩算法也会产生“stop the world”,不能和java程序并发执行。在压缩过程中一些对象内存地址会发生改变,java程序只能等待压缩完成后才能继续。

复制算法

复制算法简单来说就是把内存一分为二,但只使用其中一份,在垃圾回收时,将正在使用的那份内存中存活的对象复制到另一份空白的内存中,最后将正在使用的内存空间的对象清除,完成垃圾回收。

复制算法相对标记压缩算法来说更简洁高效,但它的缺点也显而易见,它不适合用于存活对象多的情况,因为那样需要复制的对象很多,复制性能较差,所以复制算法往往用于内存空间中新生代的垃圾回收,因为新生代中存活对象较少,复制成本较低。它另外一个缺点是内存空间占用成本高,因为它基于两份内存空间做对象复制,在非垃圾回收的周期内只用到了一份内存空间,内存利用率较低。

小结

以上我们介绍了常见的垃圾回收算法,这些算法各有各的优缺点,但在JVM中并不是单纯的使用特定的算法,而是使用的一种叫垃圾回收器的东西,垃圾回收器可以看做一系列算法的不同组合,在不同的场景使用合适的垃圾回收器,才能起到事半功倍的效果。我们下一篇将介绍垃圾回收器。

参考资料:

《实战Java虚拟机》 葛一鸣

《深入理解Java虚拟机(第2版)》 周志明

深入理解JVM(四)——垃圾回收算法的更多相关文章

  1. 深入理解JVM一垃圾回收算法

    我们都知道java语言与C语言最大的区别就是内存自动回收,那么JVM是怎么控制内存回收的,这篇文章将介绍JVM垃圾回收的几种算法,从而了解内存回收的基本原理. 一.stop the world 在介绍 ...

  2. 深入理解JVM(五) -- 垃圾回收算法

    上篇文章我们了解到哪些内存区域和哪些对象可以被回收,这篇文章我们就来了解一下具体的垃圾回收算法的思路,不讨论具体的实现. 一 最基础算法 标记-清除(Mark-Swap) 为什么说他是最基础的算法,因 ...

  3. JVM(九):垃圾回收算法

    JVM(九):垃圾回收算法 在本文中,我们将从概念模型的角度探讨 JVM 是如何回收对象,包括 JVM 是如何判断一个对象已经死亡,什么时候在哪里进行了垃圾回收,垃圾回收有几种核心算法,每个算法优劣是 ...

  4. jvm详情——3、JVM基本垃圾回收算法回收策略

    JVM基本垃圾回收算法回收策略 引用计数(Reference Counting):比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的 ...

  5. JVM G1垃圾回收算法简要介绍

    JVM G1垃圾回收算法简要介绍 G1的特点 能够像CMS垃圾回收算法一样并发操作应用线程(潜台词:多核) 无需太长时间即可压缩空闲内存空间(潜台词:不会引起太多的GC停顿时间) 尽可能地让GC时长可 ...

  6. JVM学习--(四)垃圾回收算法

    我们都知道java语言与C语言最大的区别就是内存自动回收,那么JVM是怎么控制内存回收的,这篇文章将介绍JVM垃圾回收的几种算法,从而了解内存回收的基本原理. stop the world 在介绍垃圾 ...

  7. 深入理解JVM(四) -- 垃圾内存回收的判定方法和内容

    上一篇文章我们学到了对象在内存中是如何存储的已经是如何被访问的,这篇文章将介绍当内存空间不够时,虚拟机将怎样判定对象可不可以被回收已经哪些地方会发生回收. 垃圾回收主要(不是全部)发生在堆内存中,当一 ...

  8. jvm的垃圾回收算法

    一.对象存活判断判断对象是否存活一般有两种方式:1.引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收.此方法简单,无法解决对象相互循环引用的问题.2 ...

  9. JVM(四) 垃圾回收

    1. 堆内存结构 Java堆从GC的角度可以细分为:新生代(Eden区.From Survivor区和To Survivor区)和老年代. 1.1 新生代 新生代是用来存放新生的对象.一般占据堆的1/ ...

  10. 深入探究JVM之垃圾回收算法实现细节

    @ 目录 前言 垃圾回收算法实现细节 根节点枚举 安全点 安全区域 记忆集和卡表 写屏障 并发的可达性分析 低延迟GC Shenandoah ZGC 总结 前言 本篇紧接上文,主要讲解垃圾回收算法的实 ...

随机推荐

  1. Django-ORM-单表操作

    ORM字段参数及单表操作 一.字段参数 1.字段 AutoField(Field) #当model中如果没有自增列,则会自动创建一个列名为id的列 -int 自增列,必须填入参数primary_key ...

  2. ios自带的返回按键,点击不刷新页面

    1.因为是微信端页面,需要获取用户基本信息和设置微信分享朋友圈等功能,ios自带的返回键没有这个功能,导致config配置不成功,该隐藏的按钮没有隐藏. 解决方法,在子页面添加一下js代码即可.链接的 ...

  3. 【java】字节码操作技术

    asm.javassist.cglib. 1.asm 比较底层,使用的visitor设计模式. 官网:https://asm.ow2.io/ 2.javassist 官网:http://www.jav ...

  4. 最优的路线(floyd最小环)

    问题描述 学校里面有N个景点.两个景点之间可能直接有道路相连,用Dist[I,J]表示它的长度:否则它们之间没有直接的道路相连.这里所说的道路是没有规定方向的,也就是说,如果从I到J有直接的道路,那么 ...

  5. 怎么编辑PDF文件内容,PDF文件编辑方法

    怎样编辑PDF文件内容?这是一个常常困扰我们的问题,工作当中我们经常会收到PDF格式的文件,但有时的文件内容不是我们想要的或者是觉得不合理的需要改掉.但是每次有这样的问题时都没有什么好的解决方法,每次 ...

  6. rsync拉取服务器上的代码到本地

    #!/bin/sh ];then echo "The parameters must be input:file path and host" read -p "(Exa ...

  7. centos上网络服务起不来network.service failed

    前言:今天在开虚拟机,额,,,crt连不上虚拟机了,ping不通,说明虚拟机网卡挂了,去后台看下 发现报错: Job for network.service failed because the  c ...

  8. 2018-2019-2 网络对抗技术 20165206 Exp3 免杀原理与实践

    - 2018-2019-2 网络对抗技术 20165206 Exp3 免杀原理与实践 - 实验任务 1 正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己 ...

  9. 一张图看懂encodeURI、encodeURIComponent、decodeURI、decodeURIComponent的区别

    一.这四个方法的用处 1.用来编码和解码URI的 统一资源标识符,或叫做 URI,是用来标识互联网上的资源(例如,网页或文件)和怎样访问这些资源的传输协议(例如,HTTP 或 FTP)的字符串.除了e ...

  10. 使用wget命令下载网络资源

    wget是GNU/Linux下的一个非交互式(non-interactive)网络下载工具,支持HTTP.HTTPS与FTP协议,并能够指定HTTP代理服务器.虽然wget命令与curl命令相比支持的 ...