第四章 JVM垃圾回收算法
说明:在阅读本篇之前,需要知道怎么判断对象的存活与否,见《第三章 JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程》
注意:本文主要参考自《分布式Java应用:基础与实践》,与《深入理解Java虚拟机(第二版)》中的一些说法有一些不同,但是原理一致
1、三种垃圾回收算法
- 标记-清除(年老代)
- 标记-整理(即标记-压缩)(年老代)
- 复制(年轻代)
1.1、标记-清除算法

原理:
- 从根集合节点进行扫描,标记出所有的存活对象,最后扫描整个内存空间并清除没有标记的对象(即死亡对象)
适用场合:
- 存活对象较多的情况下比较高效
- 适用于年老代(即旧生代)
缺点:
- 容易产生内存碎片,再来一个比较大的对象时(典型情况:该对象的大小大于空闲表中的每一块儿大小但是小于其中两块儿的和),会提前触发垃圾回收
- 扫描了整个空间两次(第一次:标记存活对象;第二次:清除没有标记的对象)
注意:
1.2、标记整理算法

原理:
- 从根集合节点进行扫描,标记出所有的存活对象,最后扫描整个内存空间并清除没有标记的对象(即死亡对象)(可以发现前边这些就是标记-清除算法的原理),清除完之后,将所有的存活对象左移到一起。
适用场合:
- 用于年老代(即旧生代)
缺点:
- 需要移动对象,若对象非常多而且标记回收后的内存非常不完整,可能移动这个动作也会耗费一定时间
- 扫描了整个空间两次(第一次:标记存活对象;第二次:清除没有标记的对象)
优点:
- 不会产生内存碎片
注意:
- 在该情况下,内存规整,对象的内存分配采用"指针碰撞法",见《第二章 JVM内存分配》
1.3、复制算法

原理:
- 从根集合节点进行扫描,标记出所有的存活对象,并将这些存活的对象复制到一块儿新的内存(图中下边的那一块儿内存)上去,之后将原来的那一块儿内存(图中上边的那一块儿内存)全部回收掉
适用场合:
- 存活对象较少的情况下比较高效
- 扫描了整个空间一次(标记存活对象并复制移动)
- 适用于年轻代(即新生代):基本上98%的对象是"朝生夕死"的,存活下来的会很少
缺点:
- 需要一块儿空的内存空间
- 需要复制移动对象
注意:
- 在该情况下,内存规整,对象的内存分配采用"指针碰撞法",见《第二章 JVM内存分配》
- 以空间换时间:通过一块儿空内存的使用,减少了一次扫描
2、垃圾回收机制
根据《第一章 JVM内存结构》所说,年轻代分为Eden区和survivor区(两块儿:from和to),且Eden:from:to==8:1:1
1)新产生的对象优先分配在Eden区(除非配置了-XX:PretenureSizeThreshold,大于该值的对象会直接进入年老代);
2)当Eden区满了或放不下了,这时候其中存活的对象会复制到from区(这里,需要注意的是,如果存活下来的对象from区都放不下,则这些存活下来的对象全部进入年老代),之后Eden区的内存全部回收掉;注意:如果是Eden区没有满,但是来了一个小对象Eden区放不下,这时候Eden区存活对象复制到from区后,清空Eden区,之后刚才的小对象再进入Eden区
3)之后产生的对象继续分配在Eden区,当Eden区又满了或放不下了,这时候将会把Eden区和from区存活下来的对象复制到to区(同理,如果存活下来的对象to区都放不下,则这些存活下来的对象全部进入年老代),之后回收掉Eden区和from区的所有内存;
4)如上这样,会有很多对象会被复制很多次(每复制一次,对象的年龄就+1),默认情况下,当对象被复制了15次(这个次数可以通过:-XX:MaxTenuringThreshold来配置),就会进入年老代了
5)当年老代满了或者存放不下将要进入年老代的存活对象的时候,就会发生一次Full GC(这个是我们最需要减少的,因为耗时很严重)
总结:
- 年轻代:复制算法
- 年老代:标记-清除或标记-整理(前者相较于后者会快一些但是会产生内存碎片,后者相较于前者不会产生内存碎片但是由于要移动存活对象所以会慢一些)
- 以上这种年轻代与年老代分别采用不同回收算法的方式称为"分代收集算法",这也是当下企业使用的一种方式
- 每一种算法都会有很多不同的垃圾回收器去实现,在实际使用中,根据自己的业务特点做出选择就好
补充:卡表(《实战java虚拟机》)


第四章 JVM垃圾回收算法的更多相关文章
- JVM垃圾回收算法(最全)
JVM垃圾回收算法(最全) 下面是JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代.非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:j ...
- JVM垃圾回收算法及回收器详解
引言 本文主要讲述JVM中几种常见的垃圾回收算法和相关的垃圾回收器,以及常见的和GC相关的性能调优参数. GC Roots 我们先来了解一下在Java中是如何判断一个对象的生死的,有些语言比如Pyth ...
- JVM 垃圾回收算法和垃圾回收器
JVM 垃圾回收算法和垃圾回收器. 一.垃圾回收的区域 栈:栈中的生命周期是跟随线程,所以一般不需要关注. 堆:堆中的对象是垃圾回收的重点. 方法区:这一块也会发生垃圾回收,不过这块的效率比较低,一般 ...
- JVM垃圾回收算法解析
JVM垃圾回收算法解析 标记-清除算法 该算法为最基础的算法.它分为标记和清除两个阶段,首先标记出需要回收的对象,在标记结束后,统一回收.该算法存在两个问题:一是效率问题,标记和清除过程效率都不太高, ...
- JVM垃圾回收算法 及 垃圾收集器
摘自<深入理解Java虚拟机> 一.什么是: GC算法是 方法论,那么垃圾收集器就是具体的 实现. 二.四种 垃圾回收算法 1.标记-清除算法:最基础的收集算法:不足有两点:1标记和清除两 ...
- 记录JVM垃圾回收算法
垃圾回收算法可以分为三类,都基于标记-清除(复制)算法: Serial算法(单线程) 并行算法 并发算法 JVM会根据机器的硬件配置对每个内存代选择适合的回收算法,比如,如果机器多于1个核,会对年轻代 ...
- JVM 垃圾回收算法
在说垃圾回收算法之前,先谈谈JVM怎样确定哪些对象是“垃圾”. 1.引用计数器算法: 引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器-1,当 ...
- Java基础:JVM垃圾回收算法
众所周知,Java的垃圾回收是不需要程序员去手动操控的,而是由JVM去完成.本文介绍JVM进行垃圾回收的各种算法. 1. 如何确定某个对象是垃圾 1.1. 引用计数法 1.2. 可达性分析 2. 典型 ...
- JVM 垃圾回收算法及案例分析
一. 在说垃圾回收算法之前,先谈谈JVM怎样确定哪些对象是“垃圾”. 1.引用计数器算法: 引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器- ...
随机推荐
- R语言实战(九)主成分和因子分析
本文对应<R语言实战>第14章:主成分和因子分析 主成分分析(PCA)是一种数据降维技巧,它能将大量相关变量转化为一组很少的不相关变量,这些无关变量成为主成分. 探索性因子分析(EFA)是 ...
- 关于mysql中storage_engine中 MYISAM 和 INNODB 的选择
简单点说 读操作多用myisam 写操作多用innodb 不过现在大家好像基本都用innodb,本人小白一个就直接用InnoDB. MySQL自20多年前成立以来一直支持可插拔存储引擎,但在一段相当长 ...
- 线程池--ThreadPoolExecutor
线程池的实现原理 1)如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步骤 需要获取全局锁). 2)如果运行的线程等于或多于corePoolSize,则将任务加入 ...
- 机器学习之路:python 字典特征提取器 DictVectorizer
python3 学习使用api 将字典类型数据结构的样本,抽取特征,转化成向量形式 源码git: https://github.com/linyi0604/MachineLearning 代码: fr ...
- 机器学习之路: python 朴素贝叶斯分类器 MultinomialNB 预测新闻类别
使用python3 学习朴素贝叶斯分类api 设计到字符串提取特征向量 欢迎来到我的git下载源代码: https://github.com/linyi0604/MachineLearning fro ...
- [BZOJ4372]烁烁的游戏(动态点分治+线段树)
和[BZOJ3730]震波几乎一样,每个点建两棵线段树分别代表它的管辖范围内以它为LCA的路径的贡献和它对父亲的贡献. 注意点分树上的点的距离在原树上不单调,所以不能有若距离超出限制就break之类的 ...
- 浅析SDWebImage
浅析SDWebImage 在日常的开发过程中,如果去优雅的访问网络的图片并去管理每个工程必须要面对的问题,如果想要在工程里面提供易用.简洁.方便管理的解决方案还是很有挑战的,毕竟还要兼顾图片文件的缓存 ...
- python IDLE 自动提示功能
\Python27\Lib\idlelib\目录下 config-extensions.def文件修改等待时间 [AutoComplete] enable=1 popupwait=2000(2000表 ...
- 解决 git push Failed to connect to 127.0.0.1 port 45463: 拒绝连接
使用Github pull 代码突然报错: Failed to connect to 127.0.0.1 port 43421: Connection refused 使用 lsof 发现端口未被占用 ...
- SVN服务端的版本对比及创建仓库时的注意事项
SVN是一个开放源代码的版本控制系统,分为客户端和服务端.就windows系统而言,客户端通常使用 TortoiseSVN,下载地址:https://tortoisesvn.net/ ,而服务端通常 ...