Java虚拟机(四)垃圾收集算法
前言
在本系列上一篇文章中我讲到了垃圾标记算法,垃圾被标记后,GC就会对垃圾进行收集,垃圾收集有很多种算法,这篇文章就来介绍常用的垃圾收集算法的思想。
1.标记-清除算法
标记-清除算法(Mark-Sweep)是一种常见的基础垃圾收集算法,它将垃圾收集分为两个阶段:
- 标记阶段:标记出可以回收的对象。
- 清除阶段:回收被标记的对象所占用的空间。
标记-清除算法之所以是基础的,是因为后面讲到的垃圾收集算法都是在此算法的基础上进行改进的。标记-清除算法的执行的过程如下图所示。 
标记-清除算法主要有两个缺点,一个是标记和清除的效率都不高,另一个从上图就可以看出来,就是容易产生大量不连续的内存碎片,碎片太多可能会导致后续没有足够的连续内存分配给较大的对象,从而提前触发新的一次垃圾收集动作。
2.复制算法
为了解决标记-清除算法的效率不高的问题,产生了复制算法。它把内存空间划为两个相等的区域,每次只使用其中一个区域。垃圾收集时,遍历当前使用的区域,把存活对象复制到另外一个区域中,最后将当前使用的区域的可回收的对象进行回收。复制算法的执行过程如下图所示。

这种算法每次都对整个半区进行内存回收,不需要考虑内存碎片的问题,代价就是使用内存为原来的一半。
复制算法的效率跟存活对象的数目多少有很大的关系,如果存活对象很少,复制算法的效率就会很高。由于绝大多数对象的生命周期很短,并且这些生命周期很短的对象都存于新生代中,所以复制算法被广泛应用于新生代中,关于新生代中复制算法的应用,会在后面的分代收集算法中详细介绍。
3.标记-压缩算法
在新生代中可以使用复制算法,但是在老年代就不能选择复制算法了,因为老年代的对象存活率会较高,这样会有较多的复制操作,导致效率变低。标记-清除算法可以应用在老年代中,但是它效率不高,在内存回收后容易产生大量内存碎片。因此就出现了一种标记-压缩算法(Mark-Compact)算法,与标记-清除算法不同的是,在标记可回收的对象后将所有存活的对象压缩到内存的一端,使他们紧凑的排列在一起,然后对端边界以外的内存进行回收。回收后,已用和未用的内存都各自一边,如下图所示。

标记-压缩算法解决了标记-清除算法效率低和容易产生大量内存碎片的问题,它被广泛的应用于老年代中。
4.分代收集算法
Java堆区的空间划分
在Java虚拟机中,各种对象的生命周期会有着较大的差别,大部分对象生命周期很短暂,少部分对象生命周期很长,有的甚至和应用程序以及Java虚拟机的运行周期一样长。因此,应该对不同生命周期的对象采取不同的收集策略,根据生命周期长短将它们分别放到不同的区域,并在不同的区域采用不同的收集算法,这就是分代的概念。
现在主流的Java虚拟机的垃圾收集器都采用分代收集算法(Generational Collection)。Java堆区基于分代的概念,分为新生代(Young Generation)和老年代(Tenured Generation),其中新生代再细分为Eden空间、From Survivor空间和To Survivor空间。因为Eden空间大多对象生命周期很短,所以新生代的空间划分并不是均分的,HotSpot虚拟机默认Eden空间和两个Survivor空间的所占的比例为8:1。
分代收集
根据Java堆区的空间划分,垃圾收集的类型分为两种,它们分别是:
- Minor Collection:新生代垃圾收集。
- Full Collection:对新生代、老年代和永久代(JDK8 取消永久代,Full Collection扫描不到替代永久代的元空间)进行收集,又可以称作Majjor Collection。它的收集频率较低,耗时较长。
当执行一次Minor Collection时,Eden空间的存活对象会被复制到To Survivor空间,并且之前经过一次Minor Collection并在From Survivor空间存活的仍年轻的对象也会复制到To Survivor空间。
有两种情况Eden空间和From Survivor空间存活的对象不会复制到To Survivor空间,而是晋升到老年代。一种是存活的对象的分代年龄超过-XX:MaxTenuringThreshold(用于控制对象经历多少次Minor GC才晋升到老年代)所指定的阈值。另一种是To Survivor空间容量达到阈值。
当所有存活的对象被复制到To Survivor空间,或者晋升到老年代,也就意味着Eden空间和From Survivor空间剩下的都是可回收对象,如下图所示。 
这时GC执行Minor Collection,Eden空间和From Survivor空间都会被清空,而存活的对象都存放在To Survivor空间。
接下来将From Survivor空间和To Survivor空间互换位置,也就是此前的From Survivor空间成为了现在的To Survivor空间,每次Survivor空间互换都要保证To Survivor空间是空的,这就是复制算法在新生代中的应用。在老年代则采用了标记-压缩算法。
在HotSpot中,基于分代的概念,GC使用的回收算法针对新生代和老年代的特点,采用不同的垃圾收集算法。
Java虚拟机(四)垃圾收集算法的更多相关文章
- Java虚拟机学习 - 垃圾收集算法(3)
跟踪收集器 跟踪收集器采用的为集中式的管理方式,全局记录对象之间的引用状态,执行时从一些列GC Roots的对象做为起点,从这些节点向下开始进行搜索所有的引用链,当一个对象到GC Ro ...
- JAVA虚拟机垃圾回收算法原理
除了释放不再被引用的对象外,垃圾收集器还要处理堆碎块.新的对象分配了空间,不再被引用的对象被释放,所以堆内存的空闲位置介于活动的对象之间.请求分配新对象时可能不得不增大堆空间的大小,虽然可以使用的总空 ...
- Java虚拟机四:垃圾回收算法与垃圾收集器
在Java运行时的几个数据区域中,程序计数器,虚拟机栈,本地方法栈3个区域随着线程而生,随线程而灭,因此这几个区域的内存分配和回收具有确定性,不需要过多考虑垃圾回收问题,因为方法结束或者线程结束时,内 ...
- 深入理解Java虚拟机(四)——HotSpot垃圾收集器详解
垃圾收集器 新生代收集器 1.Serial收集器 特点: 单线程工作,收集的时候就会停止其他所有工作线程,用户不可知不可控,会使得用户界面出现停顿. 简单高效,是所有收集器中额外内存消耗最少的. 没有 ...
- 《深入理解Java虚拟机》垃圾收集器
说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态 ...
- 深入理解java虚拟机之垃圾收集器
Java一个重要的优势就是通过垃圾管理器GC (Garbage Collection)自动管理和回收内存,程序员无需通过调用方法来释放内存.也因此很好多的程序员可能会认为Java程序不会出现内存泄漏的 ...
- 深入理解Java虚拟机笔记——垃圾收集器与内存分配策略
目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Sto ...
- Java虚拟机:GC算法深度解析
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在前面的文章里介绍了可达性分析算法,它为我们解决了判定哪些对象可以回收的问题,接下来就该我们的垃圾收集算法出场了.不同的垃圾收集算法有各自 ...
- 《深入理解Java虚拟机》——垃圾收集器与内存分配策略
GC需要完成: 哪些内存需要回收 什么时候回收 如何回收 如何确定对象不再使用 引用计数算法 给对象添加一个引用计数器,当有一个地方引用它时,计数器值进行加1操作:当引用失效时,计数器值进行减1操作: ...
- Java虚拟机—垃圾回收算法(整理版)
1.概述 由于垃圾收集算法的实现涉及大量的程序细节.因此本节不打算过多地讨论算法的实现,只是介绍几种算法的思想及其发展过程.主要涉及的算法有标记-清除算法.复制算法.标记-整理算法.分代收集算法. 2 ...
随机推荐
- mysql 开发进阶篇系列 16 MySQL Server(myisam key_buffer)
一.概述 mysql 提供了很多参数来进行服务器的设置,当服务第一次启动的时候,所有启动参数值都是系统默认的.这些参数在很多生产环境下并不能满足实际的应用需求.在这个系列中涉及到了liunx 服务器, ...
- iOS逆向开发(5):微信强制升级的突破 | 多开 | 微信5.0
接下来的几篇文章,小程以微信为例,实战地演示一下:如何注入iOS的APP.其中使用到的知识,基本在前面的文章中都有介绍到. 小白:小程,我想用回旧版本的微信! 小程:为什么要用旧版本微信呢? 小白:你 ...
- python练习七—P2P下载
最近有些事儿比较忙,python的学习就断断续续,这个练习来得比预期的晚,不过还好,不管做什么,我都希望能认真对待,认真做好每一件事. 引入 这个练习原书中称作“使用XML-RPC进行文件共享”,题目 ...
- 这一年多来,阿里Blink测试体系如何从0走向成熟?
引言 Apache Flink是面向数据流处理和批处理的分布式开源计算框架,2016年阿里巴巴引入Flink框架,改造为Blink.2017年,阿里整合了所有流计算产品,决定以Blink引擎为基础,打 ...
- Linux软件包管理之RPM命令
目录 1.Linux软件包分类 一.源码包 二.二进制包 2.rpm 包命名规则 3.rpm包安装 4.rpm包升级 5.rpm包卸载 6.查询rpm包是否安装 7.查询软件包的详细信息 8.查询软件 ...
- OSI七层协议模型、TCP/IP四层模型和五层协议体系结构之间的关系
一.OSI七层模型 OSI七层协议模型主要是:应用层(Application).表示层(Presentation).会话层(Session).传输层(Transport).网络层(Network).数 ...
- Java BIO、NIO、AIO
同步与异步 同步与异步的概念, 关注的是 消息通信机制 同步是指发出一个请求, 在没有得到结果之前该请求就不返回结果, 请求返回时, 也就得到结果了. 比如洗衣服, 把衣服放在洗衣机里, 没有洗好之前 ...
- vue+vue-router+vuex实战
shopping vue + vue-router + vuex实现电商网站 效果展示 install 下载代码: git clone https://github.com/chenchangyuan ...
- Linux上磁盘热插拔
首先获取scsi设备的信息. [root@server2 ~]# lsscsi [:::] disk VMware, VMware Virtual S 1.0 /dev/sda [:::] cd/dv ...
- Linux查询端口是否被占用的四种方法
一个面试题,使用三种不同的方法查看8080被哪个进程占用了.通常比较熟悉的方法是netstat和lsof两种,但还有什么方法呢. 1.netstat或ss命令 netstat -anlp | grep ...