写程序的一直要和内存泄露做抗争,从C++内存泄露、JavaScript内存泄露、iPhone内存泄露、到.NET内存泄露和Silverlight内存泄露,只要是个程序,都要非常注意内存泄露的问题。否则后患无穷。在托管平台例如.NET和Java,虽然说有GC在工作,但如果非托管资源没有手工释放,GC延迟释放内存,都会让你内存飙升,让你头疼。推荐两个Siverlight和.NET的内存泄露监测和性能监控Profiler/Loading Profiling工具:

1. ANTS Memory Profiler(Redgate),点击就是下载链接,详细使用方法点击这个链接。监控内存的方法

Silverlight内存泄露工具_强引用

2. dotTrace4,Leading Profiling Tool for .NET Applications,详细使用方法点击这个链接,里面还有监控案例演示,非常详尽。

Silverlight内存泄露工具_强引用_02

用好这两个工具可以有效帮助我们监测Silverlight的内存泄露。

 

如何确定对象已经被释放而没有内存泄露

使用 ANTS Memory Profiler(Redgate)(Redgate)这个工具,把程序运行起来,打开一个Form,然后拍一张快照;关闭那个Form,再拍一张快照,两张快照比较一下,看看Form释放了吗?
如果没有释放,看看它被谁引用而导致GC不释放它。ANTS Memory Profiler的强大之处就是可以让你可以很清楚地看到这个对象正在被那些其他的对象引用着。 Redgate推荐你强烈关注没有被释放的对象是否被类型为EventHandler<T>的事件引用,这个是很常见的内存泄露处。上面的Form Close例子的解决办法也很简单,就是在Form关闭的事件中加一个EventHandler -= ...来释放事件监听就行了。EventHandler本质是Delegate,  通过它把事件Listener成为了引用者EventHandler+=...这句话把两个对象联系了起来,通过它把事件Listener成为了引用者,也就是说一个对象被另一个对象强引用,当然不能被GC释放了。解决这个内存泄露的另一个方法就是弱引用 - WeakReference,不过相对强引用会有一些性能损失。
 

GC对象回收机制

 

一个对象会不会被回收,主要看垃圾回收器引用遍历的时候能不能访问到这个引用,如果访问不到,则将被回收,如果能够访问到,则不能回收。也就是说GC回收前GC会确定对象没有任何引用。GC对“无用”对象的识别机制就是判断对象是否被“根(Root)”所引用。在这里,“根”是对一组当前正被使用,或者以后可能被使用的对象的统称,大体包括这样的对象:类型的静态字段或当前的方法参数和局部变量、CPU寄存器等。

 

 

不要到项目开发完了再做内存泄露监测!

如果你项目做完了,代码都开发完成了,再做内存监测,那就太晚了,这个时候如果发现内存泄露的问题,采取行动的代价比较大。建议你在一个Sprint做好、或者一个小模块做好、或者一个基线打好、系统可以运行起来的时候就做内存监测,这个时候最能发现系统的问题,发现问题及时修补的代价也不大。