引用类型赋值“.NET技术”为null与加速垃圾回收

简介:   在标准的Dispose模式中,提到了需要及时释放资源,却并没有进一步细说让引用等于null是否有必要。  有一些人认为等于null可以帮助垃圾回收机制早点发现并标识对象是垃圾。其他人则认为这没有任何帮助。

  在标准的Dispose模式中,提到了需要及时释放资源,却并没有进一步细说让引用等于null是否有必要。

  有一些人认为等于null可以帮助垃圾回收机制早点发现并标识对象是垃圾。其他人则认为这没有任何帮助。是否赋值为null的问题首先在方法的内部被人提起。现在,为了更好的阐述提出的问题,我们来撰写一个Winform窗体应用程序。如下:

 
 
private void button1_Click( object sender, EventArgs e)
{
Method1();
Method2();
}

private void button2_Click( object sender, EventArgs e)
{
GC.Collect();
}

private void Method1()
{
SimpleClass s
= new SimpleClass( " method1 " );
s
= null ;
//其它无关工作代码(这条注释源于回应回复的朋友的质疑)
}
private void Method2()
{
SimpleClass s
= new SimpleClass( " method2 " );
}
}

class SimpleClass
{
string m_text;

public SimpleClass( string text)
{
m_text
= text;
}

~ SimpleClass()
{
MessageBox.Show(
string .Format( " SimpleClass Disposed, tag:{0} " , m_text));
}
}

  先点击按钮1,再点击按钮2释放,我们会发现:

  q 方法Method2中的对象先被释放,虽然它在Method1之后被调用;

  q 方法Method2中的对象先被释放,虽然它不像Method1那样为对象引用赋值为null;

  在CLR托管应用程序中,存在一个根的概念,类型的静态字段、方法参数以及局部变量都可以作为根存在(值类型不能作为根,只有引用类型的指针才能作为根)。

  上面的两个方法中各自的局部变量,在代码运行过程中会在内存中各自创建一个根.在一次垃圾回收中,垃圾回收器会沿着线程栈上行检查根。检查到方法内的根时,如果发现没有任何一个地方引用了局部变量,则不管是否为变量赋值为null,都意味着该根已经被停止掉。然后垃圾回收器发现该根的引用为空,同时标记该根可被释放,这也表示着Simple类型对象所占用的内存空间可被释放。所以,在上面的这个例子中,为s指定为null丝毫没有意义(方法的参数变量也是这种情况)。

  更进一步的事实是,JIT编译器是一个经过优化的编译器,无论我们是否在方法内部为局部变量赋值为null,该语句都会被忽略掉

s = null;

  在我们将项目设置为Release模式下,上面的这行代码将根本不会被编译进运行时内。

  正式由于上面这样的分析,很多人认为为对象赋值为null完全没有必要。但是,在另外一种情况下,却要注意及时为变量赋值为null。那就是类型的静态字段。为类型对象赋值为null,并不意味着同时为类型的静态字段赋值为null:

 
 
private void button1_Click( object sender, EventArgs e)
{
SimpleClass s
= new SimpleClass( " test上海企业网站设计与制作n style="color: #800000;">" );
}

private void button2_Click( object sender, EventArgs e)
{
GC.Collect();
}
}

class SimpleClass
{
static AnotherSimpleClass asc = new AnotherSimpleClass();
string m_text;

public SimpleClass( string text)
{
m_text
= text;
}

~ SimpleClass()
{
// asc = null;
MessageBox.Show( string .Format( " SimpleClass Disposed, tag:{0} 上海企业网站制作style="color: #800000;">" , m_text));
}
}

class AnotherSimpleClass
{
~ AnotherSimpleClass()
{
MessageBox.Show(
" AnotherSimpleClass Disposed " );
}
}

  以上代码运行的结果使我们发现,当执行垃圾回收,当类型SampleClass对象被回收的时候,类型的静态字段asc并没有被回收。

  必须要将SimpleClass的终结器中注释的那条代码启用。

  字段asc才能被正确释放(注意,要点击两次释放按钮。这是因为一次垃圾回收会仅仅首先执行终结器)。之所以静态字段不被释放(同时赋值为null语句也不会像局部变量那样被运行时编译器优化掉),是因为类型的静态字段一旦被创建,该根就一直存在。所以垃圾回收器始终不会认为它是一个垃圾。非静态字段不存在这个问题。将asc改为非静态,再次运行上面的代码,会发现asc随着类型的释放而被释放。

  上文代码的例子中,让asc=null是在终结器中完成的,实际工作中,一旦我们感觉到自己的静态引用类型参数占用内存空间比较大,并且使用完毕后不再使用,则可以立刻将其赋值为null。这也许并不必要,但这绝对是一个好习惯。试想一下在一个大系统中,那些时不时在类型中出现的静态变量吧,它们就那样静静地呆在内存里,一旦被创建,就永远不离开,越来越多,越来越多。

目录
相关文章
|
存储 缓存 算法
JVM第三讲:深入理解java虚拟机之垃圾回收算法?CMS垃圾回收的基本流程?对象引用类型?
JVM第三讲:深入理解java虚拟机之垃圾回收算法?CMS垃圾回收的基本流程?对象引用类型?
737 0
|
缓存 算法 Java
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
Java面试题:深入探究Java内存模型与垃圾回收机制,Java中的引用类型在内存管理和垃圾回收中的作用,Java中的finalize方法及其在垃圾回收中的作用,哪种策略能够提高垃圾回收的效率
183 1
|
Java 运维
开发与运维技术问题之ava对象头压缩技术支持所有的Java垃圾回收器如何解决
开发与运维技术问题之ava对象头压缩技术支持所有的Java垃圾回收器如何解决
177 1
|
存储 算法 Java
技术笔记:JVM的垃圾回收机制总结(垃圾收集、回收算法、垃圾回收器)
技术笔记:JVM的垃圾回收机制总结(垃圾收集、回收算法、垃圾回收器)
370 1
|
JavaScript 前端开发 算法
【JavaScript技术专栏】深入理解JavaScript垃圾回收机制
【4月更文挑战第30天】本文深入解析JavaScript的垃圾回收机制,旨在帮助开发者理解其工作原理。内容涵盖垃圾回收的概念、标记阶段、清除阶段,以及优化策略如增量回收、分代回收和并行回收。此外,还介绍了引用计数、标记-清除等常见垃圾回收算法,并讨论了内存泄漏的原因及解决方法,强调理解垃圾回收对编写高效代码的重要性。
472 0
|
存储 开发框架 Java
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
在.NET程序开发中,为了将开发人员从繁琐的内存管理中解脱出来,将更多的精力花费在业务逻辑上,CLR提供了自动执行垃圾回收的机制来进行内存管理,开发人员甚至感觉不到这一过程的存在。.NET程序可以找出某个时间点上哪些已分配的内存空间没有被程序使用,并自动释放它们。自动找出并释放不再使用的内存空间机制,就称为垃圾回收机制。本文主要介绍.Net中的GC(垃圾回收)机制及其整体流程。
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
|
算法 Java Linux
「月光宝盒」JVM研究系列「技术总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【下部】
「月光宝盒」JVM研究系列「技术总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【下部】
320 0
「月光宝盒」JVM研究系列「技术总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【下部】
|
算法 Java 编译器
「月光宝盒」JVM研究系列「技术总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【上部】
「月光宝盒」JVM研究系列「技术总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【上部】
431 0
「月光宝盒」JVM研究系列「技术总结笔记」Java虚拟机垃圾回收认知和调优的"思南(司南)"【上部】
|
存储 前端开发 rax
「技术翻译」JVM研究系列「绝版敲门砖」带你进入JVM-ZGC垃圾回收器的时代和未来
「技术翻译」JVM研究系列「绝版敲门砖」带你进入JVM-ZGC垃圾回收器的时代和未来
316 0
|
缓存 监控 Java
Java 技术篇-用java自带的内存检测工具排查内存泄漏问题,查看java垃圾回收情况,监控java堆内存变化
Java 技术篇-用java自带的内存检测工具排查内存泄漏问题,查看java垃圾回收情况,监控java堆内存变化
551 0
Java 技术篇-用java自带的内存检测工具排查内存泄漏问题,查看java垃圾回收情况,监控java堆内存变化