今天来谈谈C# 的GC ,也就是垃圾回收机制,非常的受教,总结如下

首先:谈谈托管,什么叫托管,我的理解就是托付C# 运行环境帮我们去管理,在这个运行环境中可以帮助我们开辟内存和释放内存,开辟内存一般用new ,内存是随机分配的,释放主要靠的是GC 也就是垃圾回收机制。哪么有两个大问题 1.GC 可以回收任何对象吗?2.GC 什么时候来回收对象?回收那些对象?

对于第一个问题,GC 可以回收任何对象吗?我是这样理解的,首先要明白一点,C# 在强大也管不到非托管代码?哪么什么是非托管代码呢?比如stream (文件),connection (数据库连接),COM (组件)等等。。哪么这些对象是需要进行连接的,比如说我们写这样一句话FileStream fs = new FileStream(“d://a.txt”,FileMode.Open); 实际上已经创建了和d://a.txt 的连接,如果重复两次就会报错。哪么fs 这个对象叫做非托管对象,也就是说C#

不能自动去释放和d://a.txt 的连接。哪么对于非托管的代码怎么办,一会我来说。

对于第二个问题,GC 什么时候来回收,回收什么对象?我想后面的就不用我说了,当然是回收托管对象了。但是GC 什么时候回收?是这样的:GC 是随机的,没有人知道他什么时候来,哪么我写了一个例子,证明这一点

private void button1_Click(object sender, EventArgs e)

{

AA a = new  AA ();

AA b = new  AA ();

AA c = new  AA ();

AA d = new  AA ();

}

public class  AA{}

在讲这个例子之前,要明白什么被称之为垃圾,垃圾就是一个内存区域,没有被任何引用指向,或者不再会被用到。 哪么在第一次点击按钮的时候会生成4 个对象,第二次点击按钮的时候也会生成4 个对象,但是第一次生成的4 个对象就已经是垃圾了,因为,第一次生成的4 个对象随着 button1_Click 函数的结束而不会再被调用(或者说不能再被调用 ),哪么这个时候GC 就会来回收吗?不是的!我说了GC 是随机的,哪么你只管点你的,不一会GC 就会来回收的(这里我们可以认为,内存中存在一定数量的垃圾之后,GC 会来 ),要证明GC 来过我们把AA 类改成

public class  AA

{

~AA()

{

MessageBox .Show(" 析构函数被执行了" );

}

}

要明白,GC 清理垃圾,实际上是调用析构函数,但是这些代码是托管代码(因为里面没有涉及到Steam ,Connection 等。。)所以在析构函数中,我们可以只写一个MsgBox 来证明刚的想法;这个时候,运行你的程序,一直点击按钮,不一会就会出现一大堆的“ 析构函数被执行了”…

好了,然后让我们看看能不能改变GC 这种为所欲为的天性,答案是可以的,我们可以通过调用GC.Collect(); 来强制GC 进行垃圾回收,哪么button1_Click 修改如下

private void button1_Click(object sender, EventArgs e)

{

AA a = new  AA ();

AA b = new  AA ();

AA c = new  AA ();

AA d = new  AA ();

GC .Collect();

}

哪么在点击第一次按钮的时候,生成四个对象,然后强制垃圾回收,这个时候,会回收吗?当然不会,因为,这四个对象还在执行中(方法还没结束),当点第二次按钮的时候,会出现四次" 析构函数被执行了" , 这是在释放第一次点击按钮的四个对象,然后以后每次点击都会出现四次" 析构函数被执行了" ,哪么最后一次的对象什么时候释放的,在关闭程序的时候释放(因为关闭程序要释放所有的内存)。

好了,现在来谈谈非托管代码,刚才说过,非托管代码不能由垃圾回收释放,我们把AA 类改成如下

public class  AA

{

FileStream fs = new  FileStream ("D://a.txt" ,FileMode .Open);

~AA()

{

MessageBox .Show(" 析构函数被执行了" );

}

}

private void button1_Click(object sender, EventArgs e)

{

AA a = new  AA ();

}

如果是这样一种情况,哪么第二次点击的时候就会报错,原因是一个文件只能创建一个连接。哪么一定要释放掉第一个资源,才可以进行第二次的连接。哪么首先我们想到用 GC .Collect() ,来强制释放闲置的资源,修改代码如下:

private void button1_Click(object sender, EventArgs e)

{

GC .Collect();

AA a = new  AA ();

}

哪么可以看到,第二次点按钮的时候,确实出现了“析构函数被执行了“, 但是程序仍然错了,原因前面我说过,因为Stream 不是托管代码,所以C# 不能帮我们回收,哪怎么办?

自己写一个Dispose 方法;去释放我们的内存。代码如下:

public class  AA :IDisposable

{

FileStream fs = new  FileStream ("D://a.txt" ,FileMode .Open);

~AA()

{

MessageBox .Show(" 析构函数被执行了" );

}

#region IDisposable 成员

public  void Dispose()

{

fs.Dispose();

MessageBox .Show("dispose 执行了" );

}

#endregion

}

好了,我们看到了,继承 IDisposable 接口以后会有一个Dispose 方法(当然了,你不想继承也可以,但是接口给我们提供一种规则,你不愿意遵守这个规则,就永远无法融入整个团队,你的代码只有你一个人能看懂),好了闲话不说,这样一来我们的 button1_Click 改为private void button1_Click(object sender, EventArgs e)

{

AA a = new  AA ();

a.Dispose();

}

我们每次点击之后,都会发现执行了“ dispose 执行了”,在关闭程序的时候仍然执行了“析构函数被执行了”这意味了,GC 还是工作了,哪么如果程序改为:

private void button1_Click(object sender, EventArgs e)

{

AA a = new  AA ();

a.Dispose();

GC .Collect();

}

每次都既有“ dispose 执行了又有”“析构函数被执行了”,这意味着GC 又来捣乱了,哪么像这样包含Stream connection 的对象,就不用GC 来清理了,只需要我们加上最后一句话 GC.SuppressFinalize(this) 来告诉GC ,让它不用再调用对象的析构函数中。 那么改写后的AA 的dispose 方法如下:

public  void Dispose()

{

fs.Dispose();

MessageBox .Show("dispose 执行了" );

GC.SuppressFinalize(this);

}

C# GC 垃圾回收机制的更多相关文章

  1. JVM和GC垃圾回收机制和内存分配

    JVM运行期间 线程共享 线程私有 线程共享: 方法区 堆方法区:存放可以共享数据,静态常量,类的共有方法属性字段等,可以共享的存在方法区. 堆:存放class对象 . 线程私有:本地方法栈 虚拟机栈 ...

  2. JVM架构和GC垃圾回收机制

    深入理解系列之JDK8下JVM虚拟机(1)——JVM内存组成 https://blog.csdn.net/u011552404/article/details/80306316 JVM架构和GC垃圾回 ...

  3. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

  4. 面试官,不要再问我“Java GC垃圾回收机制”了

    Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解> ...

  5. 乐字节Java|GC垃圾回收机制、package和import

    本文接上一篇:乐字节Java|this关键字.static关键字.block块.本文是接着讲述JavaGC垃圾回收机制.package 和 import语句. 一.GC垃圾回收机制 GC全名:Garb ...

  6. 通俗易懂.NET GC垃圾回收机制(适用于小白面试,大牛勿喷)

    情景:你接到xx公司面试邀请,你怀着激动忐忑的心坐在对方公司会议室,想着等会的技术面试.技术总监此时走来,与你简单交谈后.... 技术:你对GC垃圾回收机制了解的怎么样? 你:还行,有简单了解过. 技 ...

  7. GC垃圾回收机制详解

    JVM堆相关知识    为什么先说JVM堆?  JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象.这些对象的建立方式就是那些new一类的操作 ...

  8. asp.net 之 GC (垃圾回收机制)

    今天抽时间好好整理了下GC相关知识,看了CSDN和博客园的几篇文章,有了一定的简单了解,决定根据个人理解整合一份随笔写下来,望诸位指教. 一:基础问题 1.首先需要知道了解什么是GC? GC如其名,就 ...

  9. GC垃圾回收机制,iOS内存管理。

    问题: MRC中通过调用静态方法创建的新对象,不再使用时需要对其发送release消息吗? 不需要,因为约定静态方法创建的对象会自动将其放入自动释放池,即已对其发送autorelease消息,因此不可 ...

随机推荐

  1. CentOS下搭建SVN服务器

    1.安装SVN SVN数据存储有两种方式,BDB(事务安全表类型)和FSFS(一种不需要数据库的存储系统),为了避免在服务器连接中断时锁住数据,FSFS是一种更安全也更多人使用的方式.SVN的运行方式 ...

  2. Java递归实现操作系统文件的复制、粘贴和删除功能

    通过Java IO递归实现操作系统对文件的复制.粘贴和删除功能,剪切=复制+粘贴+删除 代码示例: import java.io.BufferedInputStream; import java.io ...

  3. java代码调用oracle存储过程

    一.简介 与调用mysql存储过程类型过程都是如下 1.创建连接 Connection conn = DriverManager.getConnection(url, user, password); ...

  4. NoSQL介绍

    NoSQL(Not Only SQL),是一种非关系型数据库:说到这里,大家需要了解关系型数据库和非关系型数据库的区别,可参考:从关系型数据库到非关系型数据库. NoSQL是以key-value形式存 ...

  5. Web开发须知:URL编码与解码

    通常如果一样东西需要编码,说明这样东西并不适合传输.原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义. 例如,Url参数字符串中使用key ...

  6. SSH 端口映射(一)

    转载:http://blog.csdn.net/a351945755/article/details/21785647,http://blog.csdn.net/gaoming655/article/ ...

  7. Heartbeat+LVS构建高可用负载均衡集群

    1.heartbeat简介: Heartbeat 项目是 Linux-HA 工程的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组件,在 Heartbeat 项目里 ...

  8. log4j日志优先级导致的不输出日志

    在sae部署微信代码的时候,发现它的默认日志很不友好,看起来很费劲,详细看了一下说明发现它可以根据log4j的输出级别而分类输出,就拖了一个log4j的xml文件扔进项目代码,然后部署运行,发现没有日 ...

  9. 【MVC 4】2.使用 Razor

    作者:[美]Adam Freeman      来源:<精通ASP.NET MVC 4> Razor 是微软 MVC3 引入的视图引擎的名称,并在MVC 4 中进行了修订.视图引擎处理 A ...

  10. org.springframework.web.context.ContextLoaderListen 报错解决办法

    今天搭建SSH项目的时候出现了如下错误: 严重: Error configuring application listener of class org.springframework.web.con ...