-
如何卸载assembly?或者class5
.net的动态编译功能很好,但是有个问题,动态编译的代码,每次执行后,都会产生一个新的assembly,而且无法卸载。这个动态方法执行多次之后,就会慢慢的内存泄漏。因为每个assembly都会占用内存。
google了一下,没有发现满意的答案。唯一的答案就是,把assembly放到一个appdomain里,然后所在的appdomain卸载掉。但如果这样的话,所有的东西都得通过rpc调用了,效率非常低。
从原理上来说,已经加载的class,应该是可以卸载的。不知道是否有办法调用原生的api去卸载一个已经加载的assembly。
问题补充:
我的问题是,需要实现一个脚本操作的功能,对已有的数据进行处理,并且用到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。我以为,动态的创建和销毁代码,也是非常必要的。它实际上是未来编程语言的一个方向。
问题补充:
再次感谢RednaxelaFX兄的热情解答。使我明白DLR是怎么实现的。
ironpython是个好主意。可惜我要的不仅仅是脚本,还需要linq的查询结果。如果用ironPython的话,它返回给我的是个动态类型,虽然可以动态增加删除成员,奈何我还要对返回的数据进行处理。如果不是.net的数据控件支持的类型,我还得开发一堆数据控件或者adapter去支持它的类型,比较麻烦,我还没做好成为ironpython的开发人员的心理准备。最理想的办法,就是能卸载assembly。这样工作量就是最小的。其实,不卸载也是无所谓的,因为我可以把写好的脚本缓存起来,不必每次都生成新的assembly。客户也不会无聊到写很多脚本故意把它搞崩溃。
之所以研究这个问题,纯属心理上的洁癖,想让它有个更好的解决方案。
关于.net保护工具如何让已经加载的类重新被卸载的问题,我也不知道答案,作者也没有公布。因为这可能就是他保护技术的核心。我想,如果有办法能让程序回到一个程序集加载之前的状态,就算是完成了卸载操作。如果确信程序集不再被引用,那么应该有办法完成这个操作。不过,这一定需要非常了解clr的底层结构。
.net没有提供加载的类卸载的方法,只是出于安全性的理由,这个类可能被别的代码引用,卸载了它,就可能会出现野指针。
此外,如果类可以卸载,那么有些静态构造函数的语义,可能会被改变。因为重新加载类的时候,静态构造函数可能会再次执行。
如果类也增加引用计数之类的机制,那么,类本身也应该是可以被gc的。
既然代码可以动态的创建,那为什么不可以动态的删除?既然对对象的GC可以做到,那么对类型的GC,一样可以做到。这不过是编程语言设计者观念上的问题,不是不可逾越的障碍。
静态编译,不过是为了提高运行效率而已。如果效率可以接受,那静态编译对于编程思想的表达,并不是必须的。
也就是说,动态的产生类,动态的销毁类,完全是可行的。类也不过是数据而已。2008年12月11日 17:57
2个答案 按时间排序 按投票排序
-
采纳的答案
不,CLR的设计本来就是加载进来的class是无法卸载的。所以很多managed/unmanaged混合的程序都是采用AppDomain的workaround来解决卸载问题的。
如果你需要动态编译的内容没有复杂到要用到类,而只是一些相对独立的方法的话,那LCG(Lightweight Code Generation)是你不二的选择。LCG最基本的用法是通过System.Reflection.Emit.DynamicMethod类获取ILGenerator,动态写出需要的代码,并由DynamicMethod得到对应的委托来执行后续的调用。DynamicMethod不需要与任何类相关联,可以被GC。
上面是比较原始的做法。在.NET 3.5增添了Expression tree(System.Linq.Expressions命名空间)之后,也可以通过Expression tree来替代直接使用反射来动态生成代码。关于Expression tree可以参照之前我写的一些帖子看看。
如果你是用CodeDOM来做动态编译,但实际上只是为了得到一个方法的内容,像是这个例子里的那样,那么最好还是转用LCG或者Expression tree。
如果真的需要用到类(因为需要实现某些接口或者继承某个基类),那就只能用AppDomain的workaround了。
如果说并不是要实现接口或继承类,只是想让几个动态生成的方法共享一些变量,那可以考虑通过闭包来实现变量的共享。
如果LINQ的Expression tree功能不够,例如说需要赋值、循环等功能的话,可以考虑使用DLR中的Expression tree。DLR是以Ms-PL许可证开源的,基本上没什么使用限制。它的源码可以从CodePlex获得。2008年12月11日 18:29
-
针对问题补充的回答补充:
跟我猜的差不多,果然是为了动态执行一些用户输入的表达式。用过LINQPad的话,你可能会对它的功能感到熟悉——它也是让用户输入C#代码作为查询依据,然后动态编译那个脚本并执行LINQ查询。它是如何实现的呢?稍微调查一下就可以发现,它也是使用CodeDOM(具体来说也就是CSharpCodeProvider)来编译代码,并且将生成的程序集放在别的AppDomain里的。这种做法虽然不彻底但一点都不罕见,呵呵。
针对这个问题的使用场景,我觉得可以推荐使用IronPython 2.0。既然只是需要执行用户输入的代码,用IronPython是再合适不过了;这就是脚本语言的主要应用场景之。它与.NET的互操作相当方便,而且Python本身的语法也比较简洁。整个代码编译过程都由IronPython来解决,GC什么的问题都不用操心。IronPython里生成的对象本身也是动态的,可以添加/删除成员来改变其数据的形状,应该够用了。
mooniscrazy 写道第一,有些.net代码保护工具,就可以让clr把已经加载的类卸载,防止别人dump整个程序集。
CLR是否能卸载单个程序集而不卸载整个AppDomain,我觉得这里说得非常清楚,不必重复解释。不支持这个功能是由理由的,我在学习SSCLI的时候也关注过。问题中提到的.NET代码保护工具的工作原理我倒不清楚,如果您有什么发现的话可以告诉我吗?mooniscrazy 写道第二,Dlr的类是动态生成的。如果无法卸载动态生成的类,等着它的必定是内存泄漏。
事实上DLR动态生成的“类”只有参数列表很长的Action/Func系委托类型。这里的“类”特指CLR类(也就是普通的.NET类)。
如果您有疑问:IronPython和IronRuby都是动态类型语言,难道它们的类都不是动态生成的?没错,它们就不是动态生成的CLR类型,而是更类似于“property bag”;那些动态类在原理上就像把成员名字与成员实例联系在一起的Dictionary<string,object>而已,并不是真正的动态生成CLR类型了。这些所谓的动态类确实可以被GC,就像一个已经没有活引用指向的Dictionary对象一样。
根据现有的设计,CLR支持动态生成和GC单独的方法(通过LCG;DLR内部同样是使用LCG的),但不支持卸载单独的类型。2008年12月12日 12:36
相关推荐
.NEt 反编译、修改.NET程序的绝佳工具。 Simple Assembly Explorer by WiCKY Hu http://code.google.com/p/simple-assembly-explorer/
在应用程序域中,可以加载多个程序集中,程序集的加载可以通过 Assembly.Load() 方法来实现。 二、程序集的卸载 程序集的卸载是指从应用程序域中卸载已经加载的程序集。然而,微软并没有提供卸载程序集的方法,...
C#也提供了实现动态卸载DLL的方法,通过AppDomain来实现。AppDomain是一个独立执行应用程序的环境,当AppDomain被卸载的时候,在该环境中的所有资源也将被回收。
A method for assembly sequence planning is proposed in this paper. First, two methods for assembly sequence planning are compared, which are indirect method and direct method. Then, the limits of the ...
converted to assembly language, and how the generated assembly language code can be tweaked. That said, the main audience for this book is programmers already familiar with a high-level language, ...
Spring Boot项目使用maven-assembly-plugin根据不同环境打包成tar.gz或者zip
目前对于 Assembly, CLR 没有提供卸载 Assembly 的方法。而 Assembly 是 驻留在 Appdomain 中,Appdomain 是可以动态卸载和创建的。
This book introduces programmers to 64 bit Intel assembly language using the Microsoft Windows operating system. The book also discusses how to use the free integrated development environment, ebe, ...
Art Of Assembly Art Of Assembly.pdf
Appendices Introduction to the Appendices Appendix A: Assembly Translation Appendix B: Environment Setup Append ix C: Disassembly Appendix D: Command-line Debugging Assembly with GDB Appendix E: ...
如果您的整个业务都依赖于软件中包含的IP,或者您不希望在国际上公开您的C#或VB.NET代码,那么对代码进行混淆就成为必需,而不是奢侈。 借助SmartAssembly,您可以获得一整套模糊处理功能,包括名称处理,控制流...
EMPLANT_ASSEMBLY.pdf
assembly assembly assembly assembly
unity3d加密解密Assembly-CSharp.dll解密。。。。。。。。
Red.Gate.SmartAssembly.v.6.6.0.144 含破解补丁/注册机 www.byshang.cn“smartassembly”,是一种进步,保护和调试工具,旨在帮助。NET开发人员高效地生产出更好的软件。 smartassembly会混淆和保护您的代码,优化...
ARM Assembly Language Programming.pdf
Art Of Intel x86 Assembly
SmartAssembly keygen 注册码生成工具 使用方法: ...2、断网(必须的),复制注册码到SmartAssembly 的注册码框内,点激动...5、得到用于激活的xlm文本到SmartAssembly激活窗口的右边框,点激活。 6、Enjoy!可以联网了。
x86 assembly cheatsheet
Modern X86 Assembly Language Programming shows the fundamentals of x86 assembly language programming. It focuses on the aspects of the x86 instruction set that are most relevant to application ...