C#基础:GC机制中如何判断一个对象是否扔在被使用
Posted dotnet261010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#基础:GC机制中如何判断一个对象是否扔在被使用相关的知识,希望对你有一定的参考价值。
一、前言
这个问题涉及了GC的内部算法和机制,了解它的机制对程序员编写代码具有指导意义。对于这些算法,应该立即并且能够口述他们的基本原理。
在.NET中,引用类型对象实例通常通过引用来访问,而GC判断堆中的对象是否仍然在被使用的依据也是引用。简单来说:当没有任何引用指向堆中的某个对象实例时,这个对象就被视为不再使用。
了解了判断对象是否被使用的依据后,来看一下GC查看引用的算法。垃圾回收机制把引用分为以下两类:
- 根引用:往往指那些静态字段的引用。或者存活的局部变量的引用。
- 非根引用:指那些不属于根引用的引用,往往是对象实例中的字段。
垃圾回收时,GC从所有扔在被使用的根引用出发,遍历所有的对象实例,那些不能被遍历到的对象将被视为不再被使用而进行回收。为了更加直观地理解根引用和非根引用,下面的代码给出了一个实际的例子。
using System; namespace usingDemo { public class Root { public static Employee staticEmployee; static void Main(string[] args) { // 静态变量 staticEmployee = new Employee(); // 局部变量 Employee a = new Employee(); // 局部变量 Employee b = new Employee(); // 实例成员 a._boss = new Employee(); Console.Read(); Console.WriteLine(a); } } public class Employee { public Employee _boss; public override string ToString() { if(_boss == null) { return "没有BOSS"; } else { return "有一个BOSS"; } } } }
上面的代码中,一共拥有两个局部变量和一个静态变量,这些引用都是根引用。而其中一个局部变量a拥有一个成员实例对象,这个引用就是一个非根引用。下图展示了执行到Console.Read();这行代码时运行垃圾回收时的情况。
如上图所示,在代码中执行到Console.Read()时,存活的根引用有staticEmployee和a,前者因为它是一个公共静态变量,而后者是因为后续代码仍然使用a。通过这两个存活的根引用,GC会找到一个非根引用staticEmployee._boss,并且发现三个仍然存活的对象。而b的对象则将被视为不再使用而被释放。
这里GC侦测出b引用不再被使用从而释放了b的对象,更简单地确保b对象被视为不再被使用的方法是把b引用置为null,即b=null。
另外,当一个从根引用出发的遍历抵达一个已经被视为在使用的对象时,将结束这一个分支的遍历,这样做是为了避免死循环。
二、总结
GC通过在使用的根引用遍历所有引用的对象实例。当一个对象不能被遍历时,将被视为不再被使用。
以上是关于C#基础:GC机制中如何判断一个对象是否扔在被使用的主要内容,如果未能解决你的问题,请参考以下文章
JavaGC垃圾回收机制JavaGC如何判断对象是否可被回收Java的GC的具体回收简述
36.JVM内存分哪几个区,每个区的作用是什么如和判断一个对象是否存活java垃圾回收机制垃圾收集的方法有哪些java类加载过程类加载机制双亲委派Minor GC和Major GC