标签:
GC优点:
1.提高生产率,不用逐行检查内存是否释放。
2.Java安全策略的一部分,不会使用户错误释放内存而导致JVM崩溃。
GC算法基本两点:
1.检测出垃圾对象。
2.回收垃圾对象,释放相应堆空间。
垃圾检测一般是先建立一个根对象集合,其它对象要是从根对象起可触及就是活的,无法到达的就是垃圾。
区别活动对象和垃圾的两个基本方法是引用计数和跟踪
引用计数:GC的早期策略,队中每个对象都有一个引用计数器,当对象创建并赋给一个变量时,引用计数为1.每次赋给别的变量时,引用计数加1。当对象的引用超过了生存期或指向到了新值,对象引用减1。为0时就是垃圾,可清楚。但是该方法对多个对象的循环引用无能为力,此外还有引用数的增减带来额外开销。现在该计数已经不为人所接受了。
跟踪收集器:跟踪收集追踪从根节点开始的对象引用图,基本的追踪算法叫“标记并清除”,也就是GC的两个阶段。标记阶段,垃圾收集器遍历引用树,标记每一个遇到的对象。清除阶段,未被标记的对象被释放。可能在对象本身设置标记,要么就是用一个独立的位图来设置标记。
标记和清除通常使用两种策略来消除堆碎片:压缩和拷贝,这两种方法都是快速移动对象来减小碎片。
压缩收集器:
压缩收集器把活动对象越过空闲区滑到堆的一堆,留下另一端的大的连续空闲块。被移动的对象的引用也被更新,指向新的位置。更新被移动对象的引用有时通过一个间接对象引用层来实现的,对象的引用不实际指向堆中对象,而是指向一个对象句柄表(由它完成对象引用到堆中对象的实际位置的映射),对象被移动了,只需要更新对象句柄表的句柄值,这样程序中的对象引用不变。这种方法简化了消除堆碎片的工作,但是每次对象访问都要查一下映射表,带来了性能上的损失。
拷贝收集器:
拷贝收集器把所有的活动对象移动到一个新的区域。这种方法在追踪对象过程中随着发现而被拷贝,不再有标记和清除的区分。一般的拷贝收集算法称为“停止并拷贝”。在这个方案中,堆被分为两个区域,任何时候只使用其中一个区域。对象在某一个区域中分配,直到这个区域被耗尽时,程序执行停止,遍历这个区域,活动对象移到另一个区域,完成后程序恢复执行,对象在新的区域分配。原来的区域剩下垃圾,全清除。直到新的区域耗尽时,程序停止,活动对象又往回移,循环工作。这种方法的代价就是堆内存只能使用到一半。
停止拷贝收集器的缺点:
每次收集时,所有的活动对象都要移动来移动去。对于短生命的对象还好说,经常可以就地解决掉,可是对于长生命周期的对象就纯粹是个体力劳动了,把它挪来挪去除消耗大量的时间,没有产生任何效益。分代收集能直接让长生命周期的对象长时间的呆在一个地方按兵不动。GC 的精力可以更多的花在收集短命对象上。
分代收集器:
分代收集能直接让长生命周期的对象长时间的呆在一个地方按兵不动。GC 的精力可以更多的花在收集短命对象上。这种方法里,堆被分成两个或更多的子堆,每一个堆为一“代”对象服务。最年幼的那一代进行最频繁的垃圾收集。因为多数对象是短命的,只有很小部分的年幼对象可以在经历第一次收集后还存活。如果一个最年幼的对象经历了好几次垃圾收集后仍是活着的,那这个对象就成为寿命更高的一代,它被转移到另外一个子堆中去。年龄更高一代的收集没有年轻一代来得频繁。每当对象在所属的年龄代中变得成熟(多次垃圾收集后仍幸存)之后,就可以转移到更高年龄的一代中去。分代收集除了可应用于拷贝算法,也可以应用于标记清除算法。不管在哪种情况下,把堆按照对象年龄分组可以提高最基本的垃圾收集的性能。
http://blog.csdn.net/zouxinfox/article/details/1594216
http://www.bianceng.cn/Programming/Java/201101/22727.htm
标签:
原文地址:http://www.cnblogs.com/tuifeideyouran/p/4586933.html