GC机制对非托管资源的回收

原创 2004年07月03日 13:00:00

对于托管资源,.net的GC机制可以很好的回收无用的垃圾。然而对于非托管资源,必须自己手动释放掉其资源。什么是非托管资源呢?例如文件访问、网络访问等,这些资源都需要手动清除。难道真的是这样吗?我们来做个实验。建立一个类

public class FileGC
{
?private Stream m_srFile;
?public FileGC()
?{
??m_srFile=File.Open(".//1.txt",FileMode.OpenOrCreate,FileAccess.Write);
?}
}
这个类很简单,实例化时创建或打开1.txt文件。


建立一个窗体,上面添加一个按钮。窗体初始化时添加如下事件
private void Form1_Load(object sender, System.EventArgs e)
{
?FileGC f=new FileGC();
}

按钮中添加如下事件。
private void btGC_Click(object sender, System.EventArgs e)
{
?GC.Collect();
}

这样,当窗体初始化时就会产生一个无用的资源FileGC f,为了验证1.txt是否被打开,你可以尝试删除掉目录下的1.txt。此时你会发现会提示文件正在被访问。当你按下按钮,程序强制进行GC操作,此时f对象被销毁。其实此时的m_srFile对象也被销毁了,为了验证,尝试删除1.txt。成功。
等一等,这里有个冲突不是说GC机制对于非托管资源无法释放吗?那m_srFile对象对于1.txt的连接是怎么关闭的呢?

理论上应该是f对象被清除,然而由于m_srFile对象使用的是非托管资源而无法被清除。可是事实却是m_srFile对象被清除了。难道Stream有自己清除的功能?光猜想是不够的。使用ILDasm打开mscorlib.dll文件,这个文件是.NET Framework类的主要配件,mscorlib.dll包含了大部分我们使用的类。把它拆了看看吧。

打开后看到一个树形目录System->System.IO->Stream看看这个类的声明。
.class public abstract auto ansi beforefieldinit Stream
?????? extends System.MarshalByRefObject
?????? implements System.IDisposable
extends System.MarshalByRefObject
说明该类派生自System.MarshalByRefObject
implements System.IDisposable并使用了System.IDisposable接口。

察看整个Stream的IL没有发现回收文件句柄的操作。是否我们找错了方向,看看File.Open打开文件使用了类型。
System.IO.File.Open看看它的代码。
.method public hidebysig static
??????? class 'System.IO'.'FileStream'
??????? 'Open'(string 'path',
?????????????? valuetype 'System.IO'.'FileMode' 'mode',
?????????????? valuetype 'System.IO'.'FileAccess' 'access',
?????????????? valuetype 'System.IO'.'FileShare' 'share') cil managed
原来返回类型是FileStream,而不是Stream。让我们来看看FileStream的类型。

首先看看类型的定义
class public auto ansi beforefieldinit 'FileStream' extends 'System.IO'.'Stream'
可以看到由于FileStream继承自Stream,因此在File.Open打开后可以转换为Stream。向下看,你会看到Finalize方法。对就是它,当GC发现它无用,执行清除其占用内存前所作的操作。名曰析构函数,这里的情况可和C++有类似的地方。

打开这个方法。你会发现一条重要语句
callvirt?? instance void 'System.IO'.'FileStream'::'Dispose'(bool)
原来在执行GC操作前执行了Dispose方法。这下我们明白了,原来.net已经为我们做好了这些事情。同样我也察看了其他一些资源比如网络等,发现.net已经为我们做好了这些操作。虽然是非托管资源,可是大家完全不用担心资源泄漏问题。除非你使用的是API函数打开的,那么你就必须自己写好Finalize方法。
本人能力很浅,错误之处还忘高手予以批评指正。也欢迎对于.net运行环境感兴趣的志同道合的朋友共同讨论问题。
联系方式:
QQ:85627584
邮箱:fjl716@163.com

GC是什么?为什么要有GC?

GC:Java的垃圾回收器。 Java是由C++发展来的。 它摈弃了C++中一些繁琐容易出错的东西。其中有一条就是这个GC。 写C/C++程序,程序员定义了一个变量,就是在内存中开辟了一...
  • CrazyingDays
  • CrazyingDays
  • 2014年03月18日 18:22
  • 4294

jvm GC日志解读

1.Parallel Scavenge 这是一款年轻代GC器。 293.271: [GC [PSYoungGen: 300865K->6577K(310720K)] 392829K->108873K(...
  • chuchus
  • chuchus
  • 2016年05月04日 10:21
  • 1845

.NET中的托管资源与非托管资源

托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源。托管资源的回收工作是不需要人工干预的,有.NET运行库在合适调用垃圾回收器进行回收。 非托管资源指的是.NET不知道如何...
  • WuLex
  • WuLex
  • 2018年01月07日 21:50
  • 84

C# 托管资源和非托管资源

托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源。托管资源的回收工作是不需要人工干预的,有.NET运行库在合适调用垃圾回收器进行回收。          非托管资源指的是...
  • zlwzlwzlw
  • zlwzlwzlw
  • 2012年08月29日 09:37
  • 19438

JDK7的5种GC类型

SerialGC ParallelGC ParallelOld GC (Parallel Compacting GC) ConcurrentMark & Sweep GC  (or “CMS”)...
  • dfsaggsd
  • dfsaggsd
  • 2016年03月17日 09:56
  • 2871

Java GC基本算法

1、JVM内存组成结构 JVM内存结构由堆、栈、本地方法栈、方法区等部分组成,结构图如下所示: 1)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms...
  • HEYUTAO007
  • HEYUTAO007
  • 2014年07月26日 23:04
  • 13474

对于托管资源和非托管资源的理解

在.net 编程环境中,系统的资源分为托管资源和非托管资源。 对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的只是了解.net CLR如何做这些操作。也就是说...
  • WuLex
  • WuLex
  • 2018年01月07日 21:53
  • 57

托管资源和非托管资源

 在.net 编程环境中,系统的资源分为托管资源和非托管资源。  对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的只是了解.net CLR如何做这些操作。也就是...
  • liangjin1126
  • liangjin1126
  • 2008年07月16日 15:18
  • 5700

java中,什么是GC?GC的基本原理。

1.什么是GC  GC(GarbageCollection)是垃圾回收机制,在Java中开发人员无法使用指针来自由的管理内存,GC是JVM对内存(实际上就是对象)进行管理的方式。GC使得Java开发...
  • uniquewonderq
  • uniquewonderq
  • 2015年06月08日 09:14
  • 5458

JVM的GC简介和实例

本文是一次内部分享中总结了jvm gc的分类和一些实例, 内容是introduction级别的,供初学人士参考. 成文仓促,难免有些错误,如果有大牛发现,请留言,我一定及时更正,谢谢! JVM内存...
  • huoyunshen88
  • huoyunshen88
  • 2013年10月21日 21:52
  • 2769
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:GC机制对非托管资源的回收
举报原因:
原因补充:

(最多只允许输入30个字)