.net的垃圾收集器
2008-08-05 18:50
176 查看
垃圾收集器用来在.net中进行内存管理,它运行时,会在堆中删除不再引用的所有对象,在完成删除动作后,堆会立即把对象分散开来,与已经释放的内存混合在一起,在移动对象时候,这些对象的所有引用都需要用正确的
新地址来更新,但垃圾收集器会处理更新问题。
到目前为止,windows平台已经使用了两种技术来释放进程向系统动态请求的内存:
1:完全以手工方式使应用程序代码完成这些工作(C++)。
2:让对象维护引用计数。(com计数)
托管代码定义
以运行库为目标的代码称为托管代码
C++分成两种,一种是托管C++,另外一种是非托管C++
C#是以运行库为目标设计的,因此用C#编写的代码基本上为托管代码
不以运行库为目标的代码称为非托管代码
.NET提供了与非托管代码互操作的服务,比如与COM互操作的Interop服务
.NET平台在内存管理方面提供了GC(Garbage Collection),负责自动释放托管资源和内存回收的工作,但它无
法对非托管资源进行释放,这时我们必须自己提供方法来释放对象内分配的非托管资源,比如你在对象的实现代
码中使用了一个COM对象。
最简单的办法,可以通过实现protected void Finalize()来释放非托管资源,因为GC在释放对象时会检查该对
象是否实现了Finalize()方法,如果是则调用它。但这样会降低效率……
有一种更好的,那就是通过实现一个接口显式的提供给客户调用端手工释放对象的方法,而不是傻傻的等着GC来
释放我们的对象(何况效率又那么低)。
System 命名空间内有一个 IDisposable 接口,拿来做这事非常合适,就省得我们自己再声明一个接口了。
另外,这种实现并不一定要使用了非托管资源后才用,如果你设计的类会在运行时有大些的实例(像GIS 中的
Geometry),为了优化程序性能,你也可以通过实现该接口让客户调用端在确认不需要这些对象时手工释放它们
。
实现过程
Code
using System;
using System.Collections.Generic;
using System.Text;
namespace Example20
{
class Program
{
class Class1 : IDisposable
{
//析构函数,编译后变成 protected void Finalize(),GC会在回收对象前调用该方法
Class1()
{
Dispose(false);
}
//通过实现该接口,客户可以显式地释放对象,而不需要等待GC来释放资源,据说那样会降低效率
void IDisposable.Dispose()
{
Dispose(true);
}
//将释放非托管资源设计成一个虚函数,提供在继承类中释放基类的资源的能力
protected virtual void ReleaseUnmanageResources()
{
//Do something
}
//私有函数用以释放非托管资源
private void Dispose(bool disposing)
{
ReleaseUnmanageResources();
//为true时表示是客户显式调用了释放函数,需通知GC不要再调用对象的Finalize方法
//为false时肯定是GC调用了对象的Finalize方法,所以没有必要再告诉GC你不要调用我的
Finalize方法
if (disposing)
{
//清理托管的代码
4000
GC.SuppressFinalize(this);//请求对象不要调用指定的对象的终结器
}
}
}
static void Main(string[] args)
{
//tmpObj1没有手工释放资源,就等着GC来慢慢的释放它
Class1 tmpObj1 = new Class1();
//tmpObj2调用了Dispose方法,比等着GC来释放它效率要高一些
Class1 tmpObj2 = new Class1();
((IDisposable)tmpObj2).Dispose();
}
}
}
总结的就是这些了!
新地址来更新,但垃圾收集器会处理更新问题。
到目前为止,windows平台已经使用了两种技术来释放进程向系统动态请求的内存:
1:完全以手工方式使应用程序代码完成这些工作(C++)。
2:让对象维护引用计数。(com计数)
托管代码定义
以运行库为目标的代码称为托管代码
C++分成两种,一种是托管C++,另外一种是非托管C++
C#是以运行库为目标设计的,因此用C#编写的代码基本上为托管代码
不以运行库为目标的代码称为非托管代码
.NET提供了与非托管代码互操作的服务,比如与COM互操作的Interop服务
.NET平台在内存管理方面提供了GC(Garbage Collection),负责自动释放托管资源和内存回收的工作,但它无
法对非托管资源进行释放,这时我们必须自己提供方法来释放对象内分配的非托管资源,比如你在对象的实现代
码中使用了一个COM对象。
最简单的办法,可以通过实现protected void Finalize()来释放非托管资源,因为GC在释放对象时会检查该对
象是否实现了Finalize()方法,如果是则调用它。但这样会降低效率……
有一种更好的,那就是通过实现一个接口显式的提供给客户调用端手工释放对象的方法,而不是傻傻的等着GC来
释放我们的对象(何况效率又那么低)。
System 命名空间内有一个 IDisposable 接口,拿来做这事非常合适,就省得我们自己再声明一个接口了。
另外,这种实现并不一定要使用了非托管资源后才用,如果你设计的类会在运行时有大些的实例(像GIS 中的
Geometry),为了优化程序性能,你也可以通过实现该接口让客户调用端在确认不需要这些对象时手工释放它们
。
实现过程
Code
using System;
using System.Collections.Generic;
using System.Text;
namespace Example20
{
class Program
{
class Class1 : IDisposable
{
//析构函数,编译后变成 protected void Finalize(),GC会在回收对象前调用该方法
Class1()
{
Dispose(false);
}
//通过实现该接口,客户可以显式地释放对象,而不需要等待GC来释放资源,据说那样会降低效率
void IDisposable.Dispose()
{
Dispose(true);
}
//将释放非托管资源设计成一个虚函数,提供在继承类中释放基类的资源的能力
protected virtual void ReleaseUnmanageResources()
{
//Do something
}
//私有函数用以释放非托管资源
private void Dispose(bool disposing)
{
ReleaseUnmanageResources();
//为true时表示是客户显式调用了释放函数,需通知GC不要再调用对象的Finalize方法
//为false时肯定是GC调用了对象的Finalize方法,所以没有必要再告诉GC你不要调用我的
Finalize方法
if (disposing)
{
//清理托管的代码
4000
GC.SuppressFinalize(this);//请求对象不要调用指定的对象的终结器
}
}
}
static void Main(string[] args)
{
//tmpObj1没有手工释放资源,就等着GC来慢慢的释放它
Class1 tmpObj1 = new Class1();
//tmpObj2调用了Dispose方法,比等着GC来释放它效率要高一些
Class1 tmpObj2 = new Class1();
((IDisposable)tmpObj2).Dispose();
}
}
}
总结的就是这些了!
相关文章推荐
- .Net Discovery 系列之三--深入理解.Net垃圾收集机制(上)
- what’s new in the .NET CLR 4.0/4.5 GC (.NET 4/4.5里新的垃圾收集机制)
- .NET中通过垃圾收集器(GC)对资源进行主动释放示例
- Net垃圾收集一点领悟
- 黑马程序员——.NET中的垃圾收集机制
- .Net Discovery 系列之七--深入理解.Net垃圾收集机制(拾贝篇)
- .Net CLR垃圾收集原理(Understanding .net CLR garbage collection)
- [经典文章翻译]垃圾收集: 在Microsoft .NET Framework中的自动化内存管理 - 第一部分
- [经典文章翻译]垃圾收集: 在Microsoft .NET Framework中的自动化内存管理 - 第二部分
- 学习笔记(3)——.net中的垃圾收集(翻译)
- 摘抄:.NET垃圾回收和资源管理
- JVM垃圾收集器与内存分配策略
- 转:ASP.NET 2.0 中收集的小功能点
- ASP.NET AJAX(开发代号Atlas)重要参考资源大收集
- JVM学习(一)、垃圾收集器简介
- javascript垃圾收集机制与内存泄漏详细解析
- javascript垃圾收集机制与内存泄漏详细解析
- jvm系列(一): java GC算法 垃圾收集器
- 垃圾收集器与内存分配策略
- java虚拟机(jvm)垃圾收集算法剖析