java垃圾回收机制通俗的解释

小伙伴一看原来是讲JAVA的,有人会说我不搞JAVA,这个于我何干?唉,这就是个急功近利的社会,大家要了解思想,思想高于一切懂吗?我每天基本游走在C++和JAVA之间,它们有什么差别呢,唯一的差别只表现形式不一样,其它无二,好了废话少说,进入正题吧。
JAVA的垃圾回收机制是采用类似标记-清理算法,在讲它之前先思考以下几个问题

* 如何标记?
* 什么时候启动垃圾回收,在智能指针里做这事很简单,当引用计数为0时
* 启动垃圾回收时,用户程序能否继续运行?

好了,大家听我娓娓道来。。。
在JAVA的世界所有的对象(除了基本类型外,如int)都是在堆上创建的,这些对象都会被记录在数据结构表中,然后从根开始遍历这些对象,这就是传说中的标记,什么?根?尼玛好抽象啊!呵呵,是有点抽象,其实就是在程序运行过程中产生的全局变量、静态变量、局部变量、临时变量等,就是使用这些变量去遍历堆上的对象,为了体贴看博客的同志们,我还是画张图吧!
java垃圾回收机制通俗的解释_第1张图片
看到了吗?标记为黄色的对象就是要被回收的对象。这些娃如果不回收就会造成内存泄漏。

JAVA的垃圾回收技术基于”经过一段时间后依然存活的对象有可能一直存活下去“的经验,将对象分为不同世代进行管理。小伙伴们这句话的份量你们自已掂量吧
因此JVM把堆上内存分为三大块

* 新生代
* 老生代
* 永久代

现在我们按代来介绍
新生代由一个eden区和两个Survivor区组成,eden是什么呢?当然就是偷吃禁果的那个伊甸园,此处省略500字。。。小伙伴们发挥一下想象力吧,survivor是什么呢?不知道的小伙伴们查字典吧,现在咱们看一下每个空间的执行顺序吧

1. 绝大多数刚刚被创建的对象会存放在eden空间。
2. 在eden区满时(不用管它是真满还是假满),就会执行了垃圾回收(这就是启动时机),垃圾回收算法就是上一篇讲的标记-复制-清除算法(知道我的用心良苦了吧),小伙伴们猜一猜复制到哪里呢?哈哈,只要你不太笨的话一定可以猜的到,存活的对象被移动到其中一个Survivor区,没有猜对的小伙伴去面壁思过吧。
3. 此后,在eden区执行垃圾回收之后,存活的对象会被堆积在同一个survivor区。
4. 当一个survivor区满时,还在存活的对象会被移动到另一个survivor区。之后会清空已经饱和的那个survivor。
5. 在以上的步骤中重复几次依然存活的对象,就会被移动到老生代。

小伙伴们看过之后是不是觉得为什么要这么折腾啊,你们忘了吗?生命不息折腾不至。
注意事项:

* 存活的对象在被移动时,会导致用户程序并发问题,如何解决这个问题呢?JVM解决此问题的方法是“ **STOP THE WORLD** ”,即在垃圾回收的时候会暂停应用程序的执行,对于用户响应要求比较高的程序,这是致命的,但是可以通过调节相应参数来缩短STOP THE WORLD的时间。
* 在任一时刻至少一个Survivor区是空的
* 对象被移来移去是对”经过一段时间后依然存活的对象有可能一直存活下去“的经验的最有力的践行。
* 我们把发生在新生代里的垃圾回收(GC)称为minor GC

终于讲完新生代的GC,累死我了,让我喝口水,来咱们继续老生代的GC,也就是传说中的major GC。
老生代主要由一个区组成,在这个区里执行的GC算法就是我们上一篇讲的标记-清除-压缩算法,是不是简单啊,如果放到这里讲,你们一定看的很累。。。
老生代的GC虽然很简单,但是遇到了一个很严重的问题,这个问题严重到会导致GC的破产,这个问题就是如果老生代对象里引用新生代对象肿么吧,意识到问题的严重性了吗?换句话说地新生代GC时,有可能把老生代对象中引用的对象清理掉。这个问题肿么解决呢,知道大牛是怎么炼成的了吧,就是不断解决面对的问题成为小牛,然后再不断解决面对的问题成为大牛,知道菜鸟和大牛的差别吗?菜鸟遇到问题是害怕、抱怨,大牛遇到问题是兴奋,因为他们终于又可以成长啦!!!
又扯远了,看一下大牛是怎么解决这个问题的吧!其实很简单,他们做了一卡表(card table)来标记哪些老对象引用了新对象,card table的大小为512B,也就是说用位来标记的话,在老生代中的对象至多为512*8=4096个。
java垃圾回收机制通俗的解释_第2张图片
图 2: Card Table 结构


最后就永久代了,永久代就很简单啦
永久代也是由一个区组成,这个区里存的是什么呢?肯定有小伙伴们猜到是用来永久存放从老年代存活下来的对象?恭喜你答错了!!!在这个区里保存类常量、字符串常量等。小伙伴们记住千万不可想当然啊,对了这个区域也是可以发生GC的,在这里发生GC,也算做major GC。

至此,我把java的GC机制讲完了,剩下的是GC的调优,网上有很多资料,我不讲了。。。大家感兴趣的自己看下吧
总结一下吧
java GC还是很复杂的,大家知道为什么很复杂???因为大牛们想要把性能做到极致,这就是所谓的“工匠精神”,反思自己做东西的想法是什么?”能用就行”,不好意思戳到大家的痛处了,所以我们必须不断学习、思考,提升自己,才能站在巨人的肩膀上做出牛X的东西。

你可能感兴趣的:(java垃圾回收)