GC全称应该是garbage collect吧
应用程序对资源操作,通常简单分为以下几个步骤:
1、为对应的资源分配内存
2、初始化内存
3、使用资源
4、清理资源
5、释放内存
GC的工作流程主要分为如下几个步骤:
1、标记(Mark)
2、计划(Plan)
3、清理(Sweep)
4、引用更新(Relocate)
5、压缩(Compact)
(一)、标记
目标:找出所有引用不为0(live)的实例
方法:找到所有的GC的根结点(GC Root), 将他们放到队列里,然后依次递归地遍历所有的根结点以及引用的所有子节点和子子节点,将所有被遍历到的结点标记成live。弱引用不会被考虑在内
(二)、计划和清理
1、计划
目标:判断是否需要压缩
方法:遍历当前所有的generation上所有的标记(Live),根据特定算法作出决策
2、清理
目标:回收所有的free空间
方法:遍历当前所有的generation上所有的标记(Live or Dead),把所有处在Live实例中间的内存块加入到可用内存链表中去
(三)、引用更新和压缩
1、引用更新
目标: 将所有引用的地址进行更新
方法:计算出压缩后每个实例对应的新地址,找到所有的GC的根结点(GC Root), 将他们放到队列里,然后依次递归地遍历所有的根结点以及引用的所有子节点和子子节点,将所有被遍历到的结点中引用的地址进行更新,包括弱引用。
2、压缩
目标:减少内存碎片
方法:根据计算出来的新地址,把实例移动到相应的位置。
什么时候发生GC
1、当应用程序分配新的对象,GC的代的预算大小已经达到阈值,比如GC的第0代已满
2、代码主动显式调用System.GC.Collect()
3、其他特殊情况,比如,windows报告内存不足、CLR卸载AppDomain、CLR关闭,甚至某些极端情况下系统参数设置改变也可能导致GC回收
GC中的代
代(Generation)引入的原因主要是为了提高性能(Performance),以避免收集整个堆(Heap)。一个基于代的垃圾回收器做出了如下几点假设:
1、对象越新,生存期越短
2、对象越老,生存期越长
3、回收堆的一部分,速度快于回收整个堆
由于GC的代价很大,平时开发中注意一些良好的编程习惯有可能对GC有积极正面的影响,否则有可能产生不良效果。
1、尽量不要new很大的object,大对象(>=85000Byte)直接归为G2代,GC回收算法从来不对大对象堆(LOH)进行内存压缩整理,因为在堆中下移85000字节或更大的内存块会浪费太多CPU时间
2、不要频繁的new生命周期很短object,这样频繁垃圾回收频繁压缩有可能会导致很多内存碎片,可以使用设计良好稳定运行的对象池(ObjectPool)技术来规避这种问题