弱引用保持的是一个GC“不可见”的引用,是指弱引用不会增加对象的引用计数,也不会阻止垃圾回收器对该对象进行回收。因此,弱引用的目标对象可以被垃圾回收器回收,而弱引用本身不会对垃圾回收造成任何影响。
弱引用的原理是,在堆上分配的每个对象都有一个头部信息,用于存储对象的类型信息、对象的大小等信息。在头部信息中,还会有一个标志位用于表示对象是否被引用。当一个对象被创建时,该标志位为“未引用”。当该对象被弱引用引用时,该标志位不会变为“已引用”,即该对象仍然会被当做未引用的对象进行处理。被强引用后,会被标记为”已引用“,当所有的强引用都消失时,该标志位会变为“未引用”,即该对象已经没有任何强引用指向它,标记的工作由GC来完成。
在垃圾回收时,GC会根据标记-清除算法对堆中的对象进行扫描和标记,标记所有仍然被引用的对象,然后回收所有未被标记的对象。对于被弱引用引用的对象,由于弱引用不会增加对象的引用计数,也不会阻止垃圾回收器回收该对象,因此在回收时,该对象会被当做未被引用的对象进行处理,然后被回收。
总之,弱引用保持的是一个GC“不可见”的引用,即弱引用不会影响垃圾回收器对目标对象的回收,因此可以用于实现一些场景,例如缓存、对象池等场景,避免长时间占用内存或造成内存泄漏。
var sb = new StringBuilder("weak");
Console.WriteLine("before GC");
Console.WriteLine(sb);
GC.Collect();//强制垃圾回收
Console.WriteLine("after GC");
Console.WriteLine(sb);
Console.ReadLine();
output
before GC
weak
after GC
weak
以下代码在release模式下:
var sb = new StringBuilder("weak");
var weak = new WeakReference(sb);
Console.WriteLine("before GC");
Console.WriteLine(weak.Target);
GC.Collect();
Console.WriteLine("after GC");
if (weak.Target == null)
{
Console.WriteLine("now it has been cleared...");
}
else
{
Console.WriteLine(weak.Target);
}
output:
before GC
weak
after GC
now it has been cleared...
在 debug 模式下,GC.Collect 方法仍然会工作,但是它的行为可能会受到一些影响。
在 debug 模式下,编译器会添加额外的调试信息到代码中,这些信息可能会影响垃圾回收器的行为。例如,编译器可能会保留一些对象的引用,以便调试器可以访问它们,这可能会导致这些对象不会被垃圾回收器回收,直到调试器不再需要它们为止。因此,当调用 GC.Collect 方法时,由于存在调试信息的影响,可能会出现一些对象无法被立即回收的情况。
此外,在 debug 模式下,垃圾回收器的性能也可能会受到一定的影响,因为编译器会添加额外的代码和调试信息,导致程序变得更加复杂和庞大,从而使垃圾回收器需要更长的时间来扫描和回收对象。
因此,如果需要在 debug 模式下进行垃圾回收操作,应该仔细考虑其影响,并进行充分的测试,以确保程序的正确性和性能。同时,还可以考虑使用其他的调试工具和技术来诊断和解决问题,避免对程序的垃圾回收行为产生不必要的影响。
所以,以上代码在debug模式下,会有截然不同的结果:
before GC
weak
after GC
weak
标签:Console,C#,weak,回收,对象,GC,引用
From: https://www.cnblogs.com/johnyang/p/17205466.html