iteye_1683
iteye_1683
2008-12-11 17:57
浏览 427

如何卸载assembly?或者class

.net的动态编译功能很好,但是有个问题,动态编译的代码,每次执行后,都会产生一个新的assembly,而且无法卸载。这个动态方法执行多次之后,就会慢慢的内存泄漏。因为每个assembly都会占用内存。
google了一下,没有发现满意的答案。唯一的答案就是,把assembly放到一个appdomain里,然后所在的appdomain卸载掉。但如果这样的话,所有的东西都得通过rpc调用了,效率非常低。
从原理上来说,已经加载的class,应该是可以卸载的。不知道是否有办法调用原生的api去卸载一个已经加载的assembly。
[b]问题补充:[/b]
我的问题是,需要实现一个脚本操作的功能,对已有的数据进行处理,并且用到linq查询,然后返回查询的结果。
查询的逻辑是未知的,由客户输入脚本来实现。查询的结果是一个二维表。但是希望查询结果返回的数据结构是自描述的。为了简化问题,就用了linq的匿名对象。
现在的做法,是用动态编译的方法,用CSharpCodeProvider动态编译客户输入的那段代码,产生一个CompilerResult,这个地方的问题的实质,是需要一个编译器。现在为了省事,就调用了c#的编译器,但是后果就是每次执行一个脚本,就会生成一个Assembly。长期执行下去,内存会慢慢变少。因此希望能将这个Assembley卸载。
Expresstion Tree比较麻烦,因为问题就是要做语法分析,如果已经成了Tree就不需要做了。
感谢RednaxelaFX兄的解答,我想xie卸载程序集还是有可能的。理由是:第一,有些.net代码保护工具,就可以让clr把已经加载的类卸载,防止别人dump整个程序集。第二,Dlr的类是动态生成的。如果无法卸载动态生成的类,等着它的必定是内存泄漏。
从编程语言的发展趋势看,总的趋势是越来越灵活。开始阶段,是针对硬件的汇编,然后是对硬件的具体实现有一定抽象作用的c语言,再到有oo特性的c++,然后是继承了GC和更过oo特性的java和c#。现在的趋势是,对编程语言本身进行编程,表现就是Aop和动态语言。
动态语言,它需要的除了动态编译以为,就是对把gc的特性扩展到类的类型本身。当一个类的代码不再被需要,它也可以被GC。我以为,动态的创建和销毁代码,也是非常必要的。它实际上是未来编程语言的一个方向。
[b]问题补充:[/b]
再次感谢RednaxelaFX兄的热情解答。使我明白DLR是怎么实现的。
ironpython是个好主意。可惜我要的不仅仅是脚本,还需要linq的查询结果。如果用ironPython的话,它返回给我的是个动态类型,虽然可以动态增加删除成员,奈何我还要对返回的数据进行处理。如果不是.net的数据控件支持的类型,我还得开发一堆数据控件或者adapter去支持它的类型,比较麻烦,我还没做好成为ironpython的开发人员的心理准备。最理想的办法,就是能卸载assembly。这样工作量就是最小的。其实,不卸载也是无所谓的,因为我可以把写好的脚本缓存起来,不必每次都生成新的assembly。客户也不会无聊到写很多脚本故意把它搞崩溃。
之所以研究这个问题,纯属心理上的洁癖,想让它有个更好的解决方案。
关于.net保护工具如何让已经加载的类重新被卸载的问题,我也不知道答案,作者也没有公布。因为这可能就是他保护技术的核心。我想,如果有办法能让程序回到一个程序集加载之前的状态,就算是完成了卸载操作。如果确信程序集不再被引用,那么应该有办法完成这个操作。不过,这一定需要非常了解clr的底层结构。
.net没有提供加载的类卸载的方法,只是出于安全性的理由,这个类可能被别的代码引用,卸载了它,就可能会出现野指针。
此外,如果类可以卸载,那么有些静态构造函数的语义,可能会被改变。因为重新加载类的时候,静态构造函数可能会再次执行。
如果类也增加引用计数之类的机制,那么,类本身也应该是可以被gc的。
既然代码可以动态的创建,那为什么不可以动态的删除?既然对对象的GC可以做到,那么对类型的GC,一样可以做到。这不过是编程语言设计者观念上的问题,不是不可逾越的障碍。
静态编译,不过是为了提高运行效率而已。如果效率可以接受,那静态编译对于编程思想的表达,并不是必须的。
也就是说,动态的产生类,动态的销毁类,完全是可行的。类也不过是数据而已。

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

相关推荐