每天下班回家后, 相信很多人都是到家后, 外衣脱了随便一扔, 鞋脱了踢到一边, 背包也是随手一放, 钥匙, 钱包, 手机也是一样. 其原因就是我们要最快的进入回家的状态 -- 躺下, 休息或者做饭, 吃东西, 看电视总之一切让自己舒服. 不管其他的, 只要达到自己的目的, 用计算机的原理来说这叫效率(时间复杂度最低), 不接受反驳.
但是带来一个问题就是, 时间长了, 屋里一定会非常的乱, 地上有很多衣服, 日用品, 当然还有零食袋等生活垃圾.
如果不清理, 在时间长了, 垃圾占用了大量的生活空间, 我们的生活空间越来越不够用了(这就是可使用的内存变小了 --- 内存泄漏), 直到有一天, 当我们下班回到家的时候, 脚都放不下了, 这个家我们就回不去了, 也就无法使用了(这就是内存不够用了 --- 内存溢出 OOM).
为了防止这样, JVM 就有了垃圾回收机制.
1.Serial GC , 单线程 GC.
如果把你的家比作一个堆内存, 把你自己比作一个 Seriale GC, 你会怎么做呢?
如果恰好你的家有两个屋子, 一个客厅, 一个卧室. 是不是可以这样呢: 首先, 做清理前的准备, 先把其中一个屋子 (卧室) 清理干净, 日常你只用另一个屋子 (客厅). 等到客厅的非常乱的时候, 作为 Seriale GC 的你可以先看下客厅里那些东西是你想要的(比如, 衣服, 鞋子, 包等) 把, 这些东西按照类别整理:
1. 衣服放到你的干净的空间(卧室厅), 并且叠好, 摞在一起;
2. 鞋子也放到你的干净的空间 (卧室) 拖鞋跟拖鞋放一起, 皮鞋跟皮鞋放一起, 布鞋跟布鞋放一起, 摆放整齐;
3. 包包, 也是放到卧室, 根据其用途, 分门别类放整齐;
当把需要的东西, 已经区分出来, 并放到干净的空间 (卧室) 后, 这时候, 你就可以大刀阔斧的清理垃圾了,(抛去需要的, 其他的都是不需要的, 无论是零食袋, 还是灰尘等, 不用区分, 直接一股脑的清理干净)因为省去了区分, 整理这个步骤, 垃圾回收还是很快的打扫完了, 这下, 我们的客厅又是一个干净的空间. 以后当我们的卧室, 又乱的时候, 我们就可以以同样的方式将有用的东西整理到客厅, 然后打扫卧室. 如此往复, 日日月月, 开心的过一辈子......
这就是垃圾回收器的 复制 - 整理 算法.
但是又有一个问题, 复制 - 整理算法, 能满足所有情况么? 是否可以通过通过这一招吃遍天下?
当然不会, 这种算法只是适合, 需要复制 - 整理的东西比较小部分的时候, 当大部分的东西都需要 复制 - 整理的时候, 这个算法就得不偿失了. 打个比方, 当你的客厅比较乱的时候, 仅仅是将衣服, 鞋子, 包包, 整理下放到卧室, 是不是很容易. 如果要是将沙发, 茶几, 冰箱, 彩电, 鱼缸, 等全都要放到卧室里, 然后仅仅是清理下零食袋, 以及一小点垃圾那么, 这样做是不是太傻了. 用计算机的术语说, 性能浪费严重.
那需要清理的东西占小部分, 大部分都是不需要清理的, 用什么办法呢?
试想一下, 这个就是我们生活中大多数的情况, 因为我们每次打扫卫生, 整理的垃圾都是占少部分, 大部分比如说像是, 沙发, 茶几, 冰箱等家电, 都是不需要清理的东西, 当然你是国民老公那就例外了.
只需要将少部分垃圾清理, 比如说, 零食袋, 将他放到垃圾袋子里跟其他垃圾一并清理出屋子. 这就是 标记 - 清除 算法. 找到零食袋放到一边等着清理(这就是标记), 将垃圾一并清理出屋子(这就是清除).
在我们 JAVA 堆内存里, 新生代 Eden, 里大部分对象都是要回收的, 所以用 复制 - 整理 算法; 老年的 Old 里大部分对象是不需要回收的, 所以用 标记 - 清除 算法.
还有一个要注意的是, 如果你是 Seriale GC, 那么在你收拾屋子的时候, 你将无法 睡觉, 洗衣服, 做饭, 干其他的事情, 只能一心一意的收拾屋子, 直到把屋子收拾完以后才能做其他的事情. 这个事情放到 JVM 里就叫做 STW(stop the world). 暂停所有的用户线程, 只做垃圾的回收. 当然这个对于性能有很大的影响. 试想一下, 当 N 多个用户在秒杀一个东西的时候, 这时候你的 JVM 在 STW, 导致服务器一段时间里属于不可用状态. 会产生什么样的后果, 那就不敢想了.
来源: https://www.cnblogs.com/DBGzxx/p/11041245.html