03 JVM 从入门到实战 | 简述垃圾回收算法
引言
之前我们学习了 JVM 基本介绍 以及 什么样的对象需要被 GC ,今天就来学习一下 JVM 在判断出一个对象需要被 GC 会采用何种方式进行 GC。在学习 JVM 如何进行垃圾回收方法时,发现所谓的 JVM 垃圾回收思想和现实生活的场景有很多相似的地方。所以本文用餐厅回收餐桌的方式类比 JVM 垃圾回收算法,应该能帮助 JVM 学习的理解和记忆。
经典垃圾回收算
标记-清除(Mark-Sweep)
研发园开了家新餐厅,餐厅老板在考虑如何回收餐盘时首先使用了最简单的方式,那就是服务员在顾客用餐的过程中,不定时的观察餐厅,针对用完餐的顾客记录他们的位置(当然一般的服务员的脑海中自行处理),统一回收他们的餐具和餐盘。但是这种回收方式会有一个明显的问题,那就是回收后的餐厅座位,很有可能是不连续的。如果后续有同行的顾客(比如小情侣... ...)想坐在一起,那很可能找不到连续的座位。

复制算法(Copying)
为了解决餐厅座位碎片化的问题,餐厅的老板提出了一个大胆的想法,这是一个很会思考的老板。把餐厅的用餐区域分成两部分 A 厅和 B 厅,当对 A 厅中的餐桌做回收时,将 A 厅中还未用完餐的顾客,"请"到 B 厅去用餐,并且让这些顾客在 B 厅中拼桌用餐(为了餐位连续)。这样所有 A 厅中的位置都空余出来了,并且 B 厅中的用餐区域和未用餐区域都是连续的!简直是强迫症晚期。看似完美的解决了回收后餐位碎片化的问题。但是依然带来了其他的一些问题。
缺点:
餐厅的运营区域是一个整体,现在只能同时对外开放 A 厅,运营空间变小了;
当有很多顾客需要从 A 厅转移到 B 厅时,效率太低;
用餐体验很差,不被骂娘才怪。
优点:
不容易产生碎片

标记-整理算法(Mark-Compact)
当实行复制算法解决餐位回收后不连续的问题,餐厅的老板针对新问题又有了新想法,只要移动顾客就可以解决碎片化问题,为啥我要将餐厅分成两个的部分呢?毕竟那样不能最大效率的利用餐厅的用餐区域。创造性的提出了标记-整理算法,结合前面两中方法的优缺点,当餐厅准备回收餐位时,移动所有未用晚餐的顾客,并且让从餐厅的第一桌开始拼桌。这样保证后面的餐桌都是已经回收了餐盘的并且回收后的座位都是连续的。这样既提高了餐厅餐桌的利用率又保证了当有大量组团顾客进店用餐时,餐厅能够提供大量的连续餐桌(这个例子不恰当,如果真的碰到一个要让人不断移动形成空位的餐厅,你怕是要开喷了)。

分代收集(Generational Collection)
如果还是用开餐厅的方式来思考 JVM 的话,可以把分代回收看做餐厅针对不同顾客的等级推出的个性化服务。分代收集算法并没有新的思想,只是根据对象存活周期的不同将内存划分为几块,一般把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,大量的对象都是“朝生夕死”,每次垃圾回收时,都可以发现大量对象死去,所以针对新生代的垃圾回收一般选择复制算法。只需要复制少量存活对象就可以完成收集。针对老年代的垃圾回收,对象的存活时间较长,就必须使用标记-清除或者标记-整理算法来进行回收。
在新生代中,绝大多数的对象都是“朝生夕死”的,新生代并不需要按照 1:1 的比例划分内存空间,而是将内存分为一个较大的 Eden 空间和一个较小的 Survivor 空间,并将 Survivor 空间分成两个较小空间,分别是 From Space 和 ToSpace。每次使用 Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另一块 Survivor 空间中。Hotspot 虚拟机默认 Eden 和 Survivor 的大小比例是 8:1,也就是每次新生代可用内存空间为整个新生代容量的 90%。

这里很显然会有一个问题,理论上每次新生代 GC 都会回收绝大多数的对象,但是无法保证 GC 存活后的对象大学都不超过整个新生代的 10%。当 Survivor 空间的内存不够用是,就需要老年代做内存担保(分配担保策略,前边两篇文章有提过,读者可自行查阅)。同样用餐厅的理论来理解,你希望把 A 厅的顾客转移到 B 厅,但是 B 厅已经没有足够空间容纳所有顾客了,这时候可以选择将顾客安置在 VIP 包厢【老年代】。并且每次在新生代 GC 中存活的对象,其年龄就会 +1,默认情况下年龄达到 15 的对象会被转移到老年代。
这里也可以简单理解为我们给餐厅的忠实吃货办了张 VIP 卡... ...
所以,同学,办卡吗?办卡享五折优惠哈!
... ...
参考文档
《深入理解Java虚拟机》周志明 著
03 JVM 从入门到实战 | 简述垃圾回收算法的更多相关文章
- java虚拟机学习-JVM调优总结-新一代的垃圾回收算法(11)
垃圾回收的瓶颈 传统分代垃圾回收方式,已经在一定程度上把垃圾回收给应用带来的负担降到了最小,把应用的吞吐量推到了一个极限.但是他无法解决的一个问题,就是Full GC所带来的应用暂停.在一些对实时性要 ...
- JVM知识(五):垃圾回收算法
在介绍垃圾回收算法之前,我们需要先了解一个词“stop the world”,stop the world会在执行某一个垃圾回收算法的时候产生,JVM为了执行垃圾回收,会暂时java应用程序的执行,等 ...
- jvm 调优(2)垃圾回收算法
可以从不同的的角度去划分垃圾回收算法: 按照基本回收策略分 引用计数(Reference Counting): 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数. ...
- JVM调优-Jva中基本垃圾回收算法
从不同的的角度去划分垃圾回收算法. 按照基本回收策略分 引用计数(Reference Counting) 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回 ...
- JVM(二) 对象存活判断和垃圾回收算法
对象的创建 概述 下面简要介绍创建对象的几个重要步骤 : 检查能否在常量池定位到一个类的符号引用,并检查这个符号代表的类是否已被加载,解析和初始化过.如果没有则执行类加载的操作.(即是说对象的引用放在 ...
- JVM内存分配策略,及垃圾回收算法
本人免费整理了Java高级资料,一共30G,需要自己领取;传送门:https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q 说起垃圾收集(Garbage Co ...
- 小师妹学JVM之:GC的垃圾回收算法
目录 简介 对象的生命周期 垃圾回收算法 Mark and sweep Concurrent mark sweep (CMS) Serial garbage collection Parallel g ...
- JVM学习总结二——垃圾回收算法
昨天总结了JVM内存分区相关的知识,这次我们将来了解下JVM的另一个核心知识点——垃圾回收算法.这一部分其实并不太难,如果对操作系统的内存处理算法有所了解,那么这部分算法其实只看名字就能明白,两者在原 ...
- JVM垃圾回收算法及回收器详解
引言 本文主要讲述JVM中几种常见的垃圾回收算法和相关的垃圾回收器,以及常见的和GC相关的性能调优参数. GC Roots 我们先来了解一下在Java中是如何判断一个对象的生死的,有些语言比如Pyth ...
随机推荐
- 微信公众号开发 包括服务器配置、java web项目搭建、tomcat手动发布web项目、微信开发所需的url和token验证 2017.12.2
https://www.cnblogs.com/klmei/p/7060879.html 基础配置很全面
- LESS的好处
今日目标: 1:今天的学习内容是在工作完成的情况下,学习Less(之所以学习Less是因为项目中使用的是Less)-------------当前进度(0%) 注意项: 务必确保在 less.js 之前 ...
- java之集合Collection 3个例子
package cn.itcast_01; import java.util.ArrayList; import java.util.Collection; /* * 集合的由来: * 我们学习的是面 ...
- 译MassTransit 快速入门
给我看代码! 下面是MassTransit的功能设置. public class YourMessage { public string Text { get; set; } } public cla ...
- j2ee 使用db.properties连接mysql数据库
转自: http://blog.csdn.net/u013815546/article/details/50808493 注: 下面的方法是未安装构架的写法,需要自己加载驱动并建立连接. 若引入了Ac ...
- distinct的用法
1. Distinct 位置 单独的distinct只能放在开头,否则报错,语法错误 例:SELECT Sid,DISTINCT(Sscore) score from t_student; [SQL ...
- bzoj 3680 吊打xxx 模拟退火
第一道模拟退火 重心嘛,就是要找到一个点,使其到所有点距离*该点权值和最小 思路:初始化一个T,mint,当T大于mint时,每次随机一个解,如果解比当前解优,直接转移,否则,以某概率(与T正相关)转 ...
- Netty自定义协议解析原理与应用
目前,大家都选择Netty做为游戏服务器框架网络通信的框架,而且目前也有很多优秀的产品是基于Netty开发的.它的稳定性,易用性和高效率性已得到广泛的认同.在游戏服务器开发中,选择netty一般就意味 ...
- 一文带你了解 Spring 5.0 WebFlux 应用场景
一.什么是 Spring WebFlux 下图截自 Spring Boot 官方网站: 结合上图,在了解 Spring WebFlux 之前,我们先来对比说说什么是 Spring MVC,这更有益我们 ...
- Python函数小节
定义函数时,默认参数必须指向不变的对象 参数为可变对象时,正常调用的时候,结果没有问题,但是当使用默认参数的时候,结果就会和理想的有差距. In [78]: def add(L=[]): ...: L ...