对垃圾搜集算法的一些理解:标记-清楚算法、复制法、垃圾生命周期划分

最近研究了下jvm调优,下面说说我对垃圾搜集算法的一些自己的理解

jessonlv-吕国栋原创文章,转载请注明出处:http://blog.csdn.net/jessonlv/article/details/19494931

垃圾搜集算法从发展历程来看,可以大致分为三种搜集算法,最基础的搜集算法是“标记-清除算法”,另外一个是后来出现的为解决“标记-清除算法”效率问题的“复制”算法,到最后发展到现在的以分代式的回收方式,对内存中的对象按照它们的生命周期划分为几代,然后再对其进行搜集回收内存。

1、标记-清除算法(mark-sweep)

就像其名字一样,这种算法先是把所有需要回收的对象进行标记,然后再一次性清除这些标记的对象,也就是分为两步1、标记,2清除。之所以前面说这是一种最基础的算法,是因为目前为止,其他的垃圾搜集算法都是以此种算法为基础,然后对此算法进行了改进,优化了这种算法的缺点,说到缺点,这种算法有两种缺点1、效率问题,对所有对象一一进行标记然后再一一进行清除,这是最原始的操作。2、连续空间问题,一一的标记和清除后,会导致大量的非连续内存空间碎片,进而导致分配不到所需要的足够长度的内存空间,这又会引发另外一次的垃圾搜集机制。

2、复制算法(coping)

这种算法在一定程度上解决了标记-清除算法效率和连续内存空间的问题,它的做法就是将内存分为两块,每次只使用其中的一块,当这块使用完的时候,其就将这块内存中还存活的对象复制到另一半的内存中去,然后将剩下已死对象的那半块全部清除,这样就不用考虑连续的问题,而且提高了效率,但是它的代价是牺牲一半的内存,这代价也太大了,对吧!!

3、分代式的垃圾搜集方式

按照对象的生命周期,将其分为年轻代(Young Generation)、年老点(Old Generation)和持久代(Permanent Generation)

IBM有专门的研究表明,大部分的新生的对象,98%都是朝生夕死的,所以在年轻代中,我们不必为内存都进行1:1比例的分配,而是将其分为一块较大的eden(中文意思是伊甸园,是不是新生内存能像在伊甸园里一样自由自在的生存的意思?笔者意淫,请勿当真啊)区和两个较小的survivor空间,每次使用的时候只是用eden和一个survivor,当需要进行垃圾搜集的时候,把这两块里面存活的对象复制到这块空的survivor中,然后就清除eden和survivor,这样做的好处是解决了基础方法的效率和空间的问题,又解决了牺牲太多内存空间的问题。Sun Hotspot虚拟机默认eden和survivor的大小比例是8:1,也就是每次只有10%的内存是“浪费”的。但是也有例外的情况,我们不能保证每次都是98%的对象死掉了,如果要是超过10%存活下来,那就要靠年老代等对其进行担保了。

年老代

在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

持久代

持久代主要是存放静态文件、方法等,持久代对垃圾搜集没有显著影响,但是有些类可能要动态生成,这个时候就需要对持久代进行较大的设置

以上拙见,个人理解如有偏差,欢迎大家提出批评意见。

posted @ 2014-02-19 17:39  jessonlv  阅读(266)  评论(0编辑  收藏  举报