原文地址:

http://nexussharp.wordpress.com/2012/04/21/castle-windsor-avoid-memory-leaks-by-learning-the-underlying-mechanics/

CASTLE WINDSOR: AVOID MEMORY LEAKS BY LEARNING THE UNDERLYING MECHANICS

Lifestyles

In am not going to explain all the different lifestyles Windsor has as you could read up on them on the Castle Wiki but for the sake of completeness I will list the most important ones and explain them in my own words

  • Singleton: This is actually the default lifestyle, means there will be only 1 instance of that class in your container (think static)
  • PerThread: There will only 1 instance per thread (think threadstatic)
  • PerWebRequest: There will only be 1 instance per web request
  • Pooled: There will be multiple instances of the same object but in a pool with a minimum pool size and a maximum pool size
  • Transient: Each time an instance is requested windsor will initialize a new one

Service Locator

Part of ASP.NET MVC 3 is the IDependencyResolver interface which is basically the contract of the service locator pattern (described by Martin Fowler here) or better said anti pattern!

If you are using Castle Windsor combined with service location you can get a lot of memory issues basically because the contract has no method for releasing your services/components.

When you are using Windsor you should always try to avoid getting an instance from the container yourself and when you have to, remember to always release the component after using it !

IComponent component = container.Resolve();
component.Act();
container.Release(component);

But why is that? Why do we need to release our components that we ask for explicitly?

Release Policy

Again this is explained very detailed on the Castle Wiki but i will list the important ones.

  • LifecycledComponentsReleasePolicy (default)
  • NoTrackingReleasePolicy

By default Windsor will use LifecycledComponentsReleasePolicy which keeps track of all components that were created, and upon releasing them, invokes all their decommission lifecycle steps.

In other words your garbage collector will not be able to cleanup if your container still tracks your component. Which will result into memory leaks. Now i’ve seen many posts and questions on the web about this where people are advising to use the NoTrackingReleasePolicy, don’t because the default release policy is actually a good thing!

Lifecycle concerns

See Castle Wiki for a detailed description.

  • Creation – commission concerns : everything happening within container.Resolve or similar method
  • destruction – decommission concerns : everything happening within and/or aftercontainer.ReleaseComponent.

A good example of a decommission concern is when your component implements IDisposable, the container will automatically recognize this as a decommission concern.

But why and exactly when does the memory leak happen?

If you look back on the lifestyles you will see that there are lifestyles, where the begin and end of the lifetime of the component is clear:

  • Singleton : the life of the component start at commission (resolve) and ends when the container is disposed
  • PerThread : the life of the component ends when the thread ends
  • PerWebRequest : …

But what about Transient and Pooled ? Especially with these you gotta watch out !

public interface IComponent { }public class MyComponent: IComponent { }public interface IDisposableComponent: IComponent,IDisposable
{bool IsDisposed { get; }
}public class MyDisposableComponent: IDisposableComponent
{public bool IsDisposed { get; private set; }public void Dispose(){IsDisposed = true;}
}public interface IService
{IDisposableComponent Component { get; }
}public class MyServiceUsingComponent: IService
{public IDisposableComponent Component { get; private set; }public MyServiceUsingComponent(IDisposableComponent component){Component = component;}
}

What happens if we resolve a transient

 container.Register(Component.For<IComponent>().ImplementedBy<MyComponent>().LifestyleTransient());
var component=container.Resolve<IComponent>();Assert.IsFalse(container.Kernel.ReleasePolicy.HasTrack(component));

So this actually means that Windsor is not tracking the component, which means the garbage collector will be able to clean up this instance.

What happens if we resolve a transient with a decommission concern for instance IDisposable

container.Register(Component.For<IDisposableComponent>().ImplementedBy<MyDisposableComponent>().LifeStyle.Transient);
var component = container.Resolve<IDisposableComponent>();
Assert.IsTrue(container.Kernel.ReleasePolicy.HasTrack(component));

So if we don’t release the component after using it, the garbage collector will not be able to pick it up as Windsor is still referencing it and your dispose method will never get invoked !

What happens if we resolve a transient component that is dependent on another transient component with a decommission concern ?

container.Register(Component.For<IDisposableComponent>().ImplementedBy<MyDisposableComponent>().LifeStyle.Transient);
container.Register(Component.For<IService>().ImplementedBy<MyServiceUsingComponent>().LifeStyle.Transient);
var service = container.Resolve<IService>();
Assert.IsTrue(container.Kernel.ReleasePolicy.HasTrack(service));

The tracking will propagate onto the parent service so again if we don’t release the service after using it, we will get a memory leak !

Always release after you are done

Container.Register(Component.For<IDisposableComponent>().ImplementedBy<MyDisposableComponent>().LifeStyle.Transient);
var component = Container.Resolve<IDisposableComponent>();
Container.Release(component);
Assert.IsTrue(component.IsDisposed);

Why does Windsor track components with a decommission concern ?

At the end of the lifetime of the component, either trough a implicit (Component or Component dependent on ends life) or explicit release (trough a container.Release), Windsor will execute all decommission steps. For instance when your component implements IDisposable, Windsor will call the Dispose method.

Conclusion

The ‘LifecycledComponentsReleasePolicy’ is great because it will track your components that have no real end of life defined and will cleanup after you. But especially be aware if you have a singleton component taking in a transient dependency with a decommission concern, because even if you release your singleton component after using it, it will not release the transient dependency immediatly, it will have to wait until your singleton’s life ends!

Because the real releasing (think disposing) of your transient dependency will happen at the end the life of the singleton component, most of the time when your application stops, only then will the container release the reference to the transient dependency and eventually call the dispose method. And even then this is just 1 instance of that transient component, so that will not cause a memory issue.

But in a real world scenario where you follow the advice of if you have to resolve yourself, you release after using the component. You will have no memory leaks !!!

So bye bye Service Locator without a release method and hello really powerfull IOC !!

避免Castle Windsor引起的内存泄露相关推荐

  1. Android中出现内存泄露的原因

    短生命周期的对象持有了长生命周期的对象,使得短生命周期对象驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再被使用,无法释放这些内存. 以下会造成内存泄露: a.数据库的cursor没有 ...

  2. Linux下正确使用getifaddrs()函数避免内存泄露

    工作中使用valgrind检测内存泄露时,发现getifaddrs()很容易导致内存泄露,下面是正确的代码: //get local ip of network card //gcc -g get_a ...

  3. 使用valgrind检测ATS插件中的内存泄露

    一.内存错误出现的场景 这几天在重构ATS插件代码的过程中遇到了烦人的内存泄露问题, 周五周六连续两天通过走查代码的方法,未能看出明显的导致内存错误的代码, 同时也觉得C和C++混合编程得到一个动态库 ...

  4. 在Ubuntu 14.04 64bit上安装Valgrind并检查内存泄露

    valgrind官网:http://valgrind.org/ 1.安装方法 第一种方式:下载目前最新的源码,编译安装,在服务器上推荐这种方式 wget http://valgrind.org/dow ...

  5. ATS插件开发中内存泄露问题的解决方法探讨

    接触ATS开发已经有几年了,开发过内核的模块,也从事过插件的开发.内存泄露问题一直是一个困扰大多数ATS开发者的头疼的问题,下面说说我自己的感受和思考.这里这关注ATS插件开发这个话题.源码的exam ...

  6. 通过define _CRTDBG_MAP_ALLOC宏来检测windows上的code是否有内存泄露

    VS中自带了内存泄露检测工具,若要启用内存泄露检测,则在程序中包括以下语句: #define _CRTDBG_MAP_ALLOC #include <crtdbg.h> 它们的先后顺序不能 ...

  7. Ubuntu下内存泄露检测工具Valgrind的使用

    在VS中可以用VLD检测是否有内存泄露,可以参考http://blog.csdn.net/fengbingchun/article/details/44195959,下面介绍下Ubuntu中内存泄露检 ...

  8. OpenCV中的内存泄露问题(cvLoadImage,cvCloneImage)

    转自:http://apps.hi.baidu.com/share/detail/30893646 在做项目的过程中,使用OpenCV经常会出现一些内存泄露问题,自己编写的程序出现问题还情有可原,但若 ...

  9. python会不会出现内存泄露_Python内存泄漏和内存溢出的解决方案

    一.内存泄漏 像Java程序一样,虽然Python本身也有垃圾回收的功能,但是同样也会产生内存泄漏的问题. 对于一个用 python 实现的,长期运行的后台服务进程来说,如果内存持续增长,那么很可能是 ...

最新文章

  1. NYOJ 366 D的小L
  2. #HTTP协议学习# (五)压缩
  3. ad20如何导入库_一文看懂如何使用(Py)Stan进行贝叶斯推理
  4. UDA机器学习基础—交叉验证
  5. Navicat——连接SQL Server数据库方法
  6. 判断是否获取到手机相机权限
  7. @Transcational特性
  8. 【转载】C++中cin、cin.get()、cin.getline()、getline()、gets()函数详解
  9. 回文质数(洛谷-P1217)
  10. [OpenGL] Stencil Shadow Algorithm
  11. 记录HttpWebRequest辅助类
  12. CF1399E1 Weights Division (easy version)
  13. 如何写一篇文献计量分析论文---citespace+vosviewer+文献计量在线分析平台
  14. chm文件打不开的解决办法
  15. LGTM : code review 行话
  16. Python中str()函数的使用(学习笔记)
  17. 域计算机软件安装统计,如何通过SCCM查找客户端计算机已安装的软件清单
  18. 淘宝直通车如何打造爆款,直通车爆款秘籍
  19. CCRC认证是什么,ISCCC与CCRC是什么关系?
  20. 网络舆情数据挖掘分析的三点方法和建议

热门文章

  1. (十六)深入浅出TCPIP之Hello CDN
  2. Linux内核 scatterlist介绍
  3. IDEA 将 SpringBoot 项目打包成jar
  4. Android RecyclerView实现九宫格效果
  5. 遭银行账号诈骗最快最有效自救法
  6. 人生有五不:不等、不管、不看、不做、不给
  7. 远程网络视频监视技术
  8. 解决: Incorrect username or password, or no permission ( Docker 方式运行 Nexus3 登陆密码不为 admin123 、重置登陆密码)
  9. 会出现 unreachable statement 的可能
  10. IPC 中 LPC、RPC 的区别和联系