JVM之GC趣解

 

  每天下班回家后,相信很多人都是到家后,外衣脱了随便一扔,鞋脱了踢到一边,背包也是随手一放,钥匙、钱包、手机也是一样。其原因就是我们要最快的进入回家的状态--躺下,休息或者做饭,吃东西,看电视总之一切让自己舒服。不管其他的,只要达到自己的目的,用计算机的原理来说这叫效率(时间复杂度最低),不接受反驳。

  但是带来一个问题就是,时间长了,屋里一定会非常的乱,地上有很多衣服,日用品,当然还有零食袋等生活垃圾。

  如果不清理,在时间长了,垃圾占用了大量的生活空间,我们的生活空间越来越不够用了(这就是可使用的内存变小了---内存泄漏),直到有一天,当我们下班回到家的时候,脚都放不下了,这个家我们就回不去了,也就无法使用了(这就是内存不够用了---内存溢出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,导致服务器一段时间里属于不可用状态。会产生什么样的后果,那就不敢想了。

 

posted on 2019-06-17 17:57  残剑今生  阅读(418)  评论(0编辑  收藏  举报