.NET CLR GC的知识点汇总

  • GC的处理流程算法

    • GC暂停进程中的全部线程。
    • GC遍历堆中的全部对象,将某个位(这个位包含在对象同步块索引的字段中)设置为0(0表示将被删除)。
    • GC检查全部活动根(根是指引用类型的变量),把活动根指向的对象标记为1,再次该对象引用的其它对象标记为1,依次类推。
    • GC将活动对象进行从新排列,让全部幸存对象在内存中紧挨在一块儿。
    • 将移动过的幸存对象的根更新固定的偏移量。
    • GC恢复进程中的全部线程。
  • GC对活动对象(活动根)的认定:性能

    • 被任何静态对象或静态字段引用。
    • 应用程序栈中引用类型的变量指向的对象。
      • 应用程序中的本地引用类型变量。
      • 应用程序方法中的引用类型参数。
    • 等待被终结(finalized)的对象。
  • GC将活动对象进行从新排列后得到的好处:线程

    • 减小活动对象的内存地址范围,提高访问活动对象的性能。
    • 让剩余的内存空间变成连续的,便于后续分配给新对象。
    • 解决原生堆(非托管堆)的内存碎片问题。
  • GC代的算法的出发点:code

    • 对象越新,生存期越短。
    • 对象越老,生存期越长。
    • 回收堆的一部分,速度快于回收整个堆。
  • GC关于代的算法流程:对象

    • 初始化堆,接下来分配的全部对象都是0代。
    • 某个时间点0代超过预算,触发一次GC回收。
    • 幸存下来的对象从0代提高到1代,此时0代不包含任何对象。
    • 对1代对象进行紧凑排列。
    • 在0代为新对象分配内存。
    • 一段时间后再次触发GC对0代进行回收。
    • 0代回收结束后发现0代的剩余空间不够用,此时会触发对1代的内存进行GC操做。
    • 1代中幸存下来的对象会被提高到2代。
    • 对1代对象进行紧凑排列。
    • 某个时间后再次触发GC对0代和1代进行回收。
    • 回收结束后发现0代的剩余空间不够用,此时会触发对2代的内存进行GC操做。
    • 对1代和2代对象进行紧凑排列。
    • 某个时间后GC对0-2代回收完成后,发现1代和2代的剩余空间太多,此时会对0-2代的内存进行从新分配。
  • GC触发的时机:索引

    • 0代超过预算时。
    • 显式调用System.GC.Collect()
    • Windows报告低内存
    • AppDomain正在被卸载
    • CLR正常关闭时
  • GC与Finalize(终结)方法进程

    • Finalize方法用于释放非托管资源的场景。
    • 定义过Finalize方法的对象在分配内存时,会被附加到支持终结的对象列表中。
    • GC在标记对象为可删除时会检查支持终结的对象列表是否存在,若是存在则会移到待终结的对象列表中。
    • 待终结的对象以及它引用的对象在判断为待删除时,这些对象仍是会被临时性地提高一个代,让这些对象存活一会来确保终结操做能正常执行。
    • GC利用一个高优先级的线程来检查待终结的对象列表并调用对象的Finalize方法,Finalize方法完成后将对象引用从该列表中删除。
    • 下一轮GC触发时刚被终结的对象以及它引用的对象会被正常回收。
  • GC与大对象内存

    • ≥85,000KB的对象为大对象。
    • 大对象被分配在独立的堆地址空间中。
    • 大对象老是2代,而且只在2代回收操做时触发回收。
    • 大对象通常不会作紧凑操做。
  • 参考资料:
    • 《CLR via C# Fourth Edition》    Jeffrey Richter
    • Fundamentals of garbage collection
      https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
    • C# Garbage Collection Active Rootshttps://stackoverflow.com/questions/8345075/c-sharp-garbage-collection-active-roots
相关文章
相关标签/搜索