- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章C# 有关Assembly.Unload详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
CLR 产品单元经理(Unit Manager) Jason Zander 在前几天一篇文章 Why isn't there an Assembly.Unload method? 中解释了为什么 CLR 中目前没有实现类似 Win32 API 中 UnloadLibrary 函数功能的 Assembly.Unload 方法。 他认为之所以要实现 Assembly.Unload 函数,主要是为了回收空间和更新版本两类需求。前者在使用完 Assembly 后回收其占用资源,后者则卸载当前版本载入更新的版本。例如 ASP.NET 中对页面用到的 Assembly 程序的动态更新就是一个很好的使用示例。但如果提供了 Assembly.Unload 函数会引发一些问题:
1.为了包装 CLR 中代码所引用的代码地址都是有效的,必须跟踪诸如 GC 对象和 COM CCW 之类的特殊应用。否则会出现 Unload 一个 Assembly 后,还有 CLR 对象或 COM 组件使用到这个 Assembly 的代码或数据地址,进而导致访问异常。而为了避免这种错误进行的跟踪,目前是在 AppDomain 一级进行的,如果要加入 Assembly.Unload 支持,则跟踪的粒度必须降到 Assembly 一级,这虽然在技术上不是不能实现,但代价太大了.
2.如果支持 Assembly.Unload 则必须跟踪每个 Assembly 的代码使用到的句柄和对现有托管代码的引用。例如现在 JITer 在编译方法时,生成代码都在一个统一的区域,如果要支持卸载 Assembly 则必须对每个 Assembly 都进行独立编译。此外还有一些类似的资源使用问题,如果要分离跟踪技术上虽然可行,但代价较大,特别是在诸如 WinCE 这类资源有限的系统上问题比较明显.
3.CLR 中支持跨 AppDomain 的 Assembly 载入优化,也就是 domain neutral 的优化,使得多个 AppDomain 可以共享一份代码,加快载入速度。而目前 v1.0 和 v1.1 无法处理卸载 domain neutral 类型代码。这也导致实现 Assembly.Unload 完整语义的困难性.
基于上述问题, Jason Zander 推荐使用其他的设计方法来回避对此功能的使用。如 Junfeng Zhang 在其 BLog 上介绍的 AppDomain and Shadow Copy,就是 ASP.NET 解决类似问题的方法.
在构造 AppDomain 时,通过 AppDomain.CreateDomain 方法的 AppDomainSetup 参数中 AppDomainSetup.ShadowCopyFiles 设置为 "true" 启用 ShadowCopy 策略;然后设置 AppDomainSetup.ShadowCopyDirectories 为复制目标目录;设置 AppDomainSetup.CachePath + AppDomainSetup.ApplicationName 指定缓存路径和文件名。 通过这种方法可以模拟 Assembly.Unload 的语义。实现上是将需要管理的 Assembly 载入到一个动态建立的 AppDomain 中,然后通过跨 AppDomain 的透明代理调用其功能,使用 AppDomain.Unload 实现 Assembly.Unload 语义的模拟。chornbe 给出了一个简单的包装类,具体代码见文章末尾.
这样做虽然在语义上能够基本上模拟,但存在很多问题和代价:
1.性能:在 CLR 中,AppDomain 是类似操作系统进程的逻辑概念,跨 AppDomain 通讯就跟以前跨进程通讯一样受到诸多限制。虽然通过透明代理对象能够实现类似跨进程 COM 对象调用的功能,自动完成参数的 Marshaling 操作,但必须付出相当的代价。Dejan Jelovic给出的例子(Cross-AppDomain Calls are Extremely Slow)中,P4 1.7G 下只使用内建类型的调用大概需要 1ms。这对于某些需要被频繁调用的函数来说代价实在太大了。如他提到实现一个绘图的插件,在 OnPaint 里面画 200 个点需要 200ms 的调用代价。虽然可以通过批量调用进行优化,但跨 AppDomain 调用效率的惩罚是肯定无法逃脱的。好在据说 Whidbey 中,对跨 AppDomain 调用中的内建类型,可以做不 Marshal 的优化,以至于达到比现有实现调用速度快 7 倍以上,...,我不知道该夸奖 Whidbey 实现的好呢,还是痛骂现有版本之烂,呵呵 。
2.易用性:需要单独卸载的 Assembly 中类型可能不支持 Marshal,此时就需要自行处理类型的管理.
3.版本:在多个 AppDomain 中如何包装版本载入的正确性.
此外还有安全方面问题。对普通的 Assembly.Load 来说,载入的 Assembly 是运行在载入者的 evidence 下,而这绝对是一个安全隐患,可能遭受类似 unix 下面通过溢出以 root 权限读写文件的程序来改写系统文件的类似攻击。而单独在一个 AppDomain 中载入 Assembly 就能够单独设置 CAS 权限,降低执行权限。因为 CLR 架构下的四级权限控制机制,最细的粒度只能到 AppDomain。好在据说 Whidbey 会加入对使用不同 evidence 载入 Assembly 的支持.
通过这些讨论可以看到,Assembly.Unload 对于基于插件模型的程序来说,其语义的存在是很重要的。但在目前和近几个版本来说,通过 AppDomain 来模拟其语义是比较合适的选择,虽然要付出性能和易用性的问题,但能够更大程度上控制功能和安全性等方面因素。长远来说,Assembly.Unload 的实现是完全可行的,Java 中对类的卸载就是最好的例子,前面那些理由实际上都是工作量和复杂度方面的问题,并不存在无法解决的技术问题.
You must also encapsulate the loaded assembly into another class, which is loaded by the new appdomain. Here's the code as it's working for me: (I've created a few custom exception types, and you'll notice I had them back - they're not descended from MarshalByRefObject so I can't just throw them from the encapsulated code) 。
--- cut first class file 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
using
System;
using
System.Reflection;
using
System.Collections;
namespace
Loader{
/* contains assembly loader objects, stored in a hash
* and keyed on the .dll file they represent. Each assembly loader
* object can be referenced by the original name/path and is used to
* load objects, returned as type Object. It is up to the calling class
* to cast the object to the necessary type for consumption.
* External interfaces are highly recommended!!
* */
public
class
ObjectLoader : IDisposable {
// essentially creates a parallel-hash pair setup
// one appDomain per loader
protected
Hashtable domains =
new
Hashtable();
// one loader per assembly DLL
protected
Hashtable loaders =
new
Hashtable();
public
ObjectLoader() {
/*...*/
}
public
object
GetObject(
string
dllName,
string
typeName,
object
[] constructorParms ){
Loader.AssemblyLoader al =
null
;
object
o =
null
;
try
{
al = (Loader.AssemblyLoader)loaders[ dllName ];
}
catch
(Exception){}
if
( al ==
null
){
AppDomainSetup setup =
new
AppDomainSetup();
setup.ShadowCopyFiles =
"true"
;
AppDomain domain = AppDomain.CreateDomain( dllName,
null
, setup );
domains.Add( dllName, domain );
object
[] parms = { dllName };
// object[] parms = null;
BindingFlags bindings = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public;
try
{
al = (Loader.AssemblyLoader)domain.CreateInstanceFromAndUnwrap(
"Loader.dll"
,
"Loader.AssemblyLoader"
,
true
, bindings,
null
, parms,
null
,
null
,
null
);
}
catch
(Exception){
throw
new
AssemblyLoadFailureException();
}
if
( al !=
null
){
if
( !loaders.ContainsKey( dllName ) ){
loaders.Add( dllName, al );
}
else
{
throw
new
AssemblyAlreadyLoadedException();
}
}
else
{
throw
new
AssemblyNotLoadedException();
}
}
if
( al !=
null
){
o = al.GetObject( typeName, constructorParms );
if
( o !=
null
&& o
is
AssemblyNotLoadedException ){
throw
new
AssemblyNotLoadedException();
}
if
( o ==
null
|| o
is
ObjectLoadFailureException ){
string
msg =
"Object could not be loaded. Check that type name "
+ typeName +
" and constructor parameters are correct. Ensure that type name "
+ typeName +
" exists in the assembly "
+ dllName +
"."
;
throw
new
ObjectLoadFailureException( msg );
}
}
return
o;
}
public
void
Unload(
string
dllName ){
if
( domains.ContainsKey( dllName ) ){
AppDomain domain = (AppDomain)domains[ dllName ];
AppDomain.Unload( domain );
domains.Remove( dllName );
}
}
~ObjectLoader(){
dispose(
false
);
}
public
void
Dispose(){
dispose(
true
);
}
private
void
dispose(
bool
disposing ){
if
( disposing ){
loaders.Clear();
foreach
(
object
o
in
domains.Keys ){
string
dllName = o.ToString();
Unload( dllName );
}
domains.Clear();
}
}
}
}
|
--- end cut 。
--- cut second class file 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
using
System;
using
System.Reflection;
namespace
Loader {
// container for assembly and exposes a GetObject function
// to create a late-bound object for casting by the consumer
// this class is meant to be contained in a separate appDomain
// controlled by ObjectLoader class to allow for proper encapsulation
// which enables proper shadow-copying functionality.
internal
class
AssemblyLoader : MarshalByRefObject, IDisposable {
#region class-level declarations
private
Assembly a =
null
;
#endregion
#region constructors and destructors
public
AssemblyLoader(
string
fullPath ){
if
( a ==
null
){
a = Assembly.LoadFrom( fullPath );
}
}
~AssemblyLoader(){
dispose(
false
);
}
public
void
Dispose(){
dispose(
true
);
}
private
void
dispose(
bool
disposing ){
if
( disposing ){
a =
null
;
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect( 0 );
}
}
#endregion
#region public functionality
public
object
GetObject(
string
typename,
object
[] ctorParms ){
BindingFlags flags = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public;
object
o =
null
;
if
( a !=
null
){
try
{
o = a.CreateInstance( typename,
true
, flags,
null
, ctorParms,
null
,
null
);
}
catch
(Exception){
o =
new
ObjectLoadFailureException();
}
}
else
{
o =
new
AssemblyNotLoadedException();
}
return
o;
}
public
object
GetObject(
string
typename ){
return
GetObject( typename,
null
);
}
#endregion
}
}
|
--- end cut 。
相关的一些资源: Why isn't there an Assembly.Unload method? http://blogs.msdn.com/jasonz/archive/2004/05/31/145105.aspx 。
AppDomains ("application domains") http://blogs.msdn.com/cbrumme/archive/2003/06/01/51466.aspx 。
AppDomain and Shadow Copy http://blogs.msdn.com/junfeng/archive/2004/02/09/69919.aspx 。
到此这篇关于C# 有关Assembly.Unload详解的文章就介绍到这了,更多相关C# 有关Assembly.Unload内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://www.cnblogs.com/ccBoy/archive/2004/07/13/23636.html 。
最后此篇关于C# 有关Assembly.Unload详解的文章就讲到这里了,如果你想了解更多关于C# 有关Assembly.Unload详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
全称“Java Virtual Machine statistics monitoring tool”(statistics 统计;monitoring 监控;tool 工具) 用于监控虚拟机的各种运
主要是讲下Mongodb的索引的查看、创建、删除、类型说明,还有就是Explain执行计划的解释说明。 可以转载,但请注明出处。  
1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发。 2>循环服务器和并发服务器
详解 linux中的关机和重启命令 一 shutdown命令 shutdown [选项] 时间 选项: ?
首先,将json串转为一个JObject对象: ? 1
matplotlib官网 matplotlib库默认英文字体 添加黑体(‘SimHei')为绘图字体 代码: plt.rcParams['font.sans-serif']=['SimHei'
在并发编程中,synchronized关键字是常出现的角色。之前我们都称呼synchronized关键字为重量锁,但是在jdk1.6中对synchronized进行了优化,引入了偏向锁、轻量锁。本篇
一般我们的项目中会使用1到2个数据库连接配置,同程艺龙的数据库连接配置被收拢到统一的配置中心,由DBA统一配置和维护,业务方通过某个字符串配置拿到的是Connection对象。  
实例如下: ? 1
1. MemoryCahe NetCore中的缓存和System.Runtime.Caching很相似,但是在功能上做了增强,缓存的key支持object类型;提供了泛型支持;可以读缓存和单个缓存
argument是javascript中函数的一个特殊参数,例如下文,利用argument访问函数参数,判断函数是否执行 复制代码 代码如下: <script
一不小心装了一个Redis服务,开了一个全网的默认端口,一开始以为这台服务器没有公网ip,结果发现之后悔之莫及啊 某天发现cpu load高的出奇,发现一个minerd进程 占了大量cpu,googl
今天写这个是为了 提醒自己 编程过程 不仅要有逻辑 思想 还有要规范 代码 这样可读性 1、PHP 编程规范与编码习惯最主要的有以下几点: 1 文件说明 2 funct
摘要:虚拟机安装时一般都采用最小化安装,默认没有lspci工具。一台测试虚拟网卡性能的虚拟机,需要lspci工具来查看网卡的类型。本文描述了在一个虚拟机中安装lspci工具的具体步骤。 由于要测试
1、修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统
目录 算术运算符 基本四则运算符 增量赋值运算符 自增/自减运算符 关系运算符 逻
如下所示: ? 1
MapperScannerConfigurer之sqlSessionFactory注入方式讲解 首先,Mybatis中的有一段配置非常方便,省去我们去写DaoImpl(Dao层实现类)的时间,这个
Linux的网络虚拟化是LXC项目中的一个子项目,LXC包括文件系统虚拟化,进程空间虚拟化,用户虚拟化,网络虚拟化,等等,这里使用LXC的网络虚拟化来模拟多个网络环境。 本文从基本的网络设备讲
? 1
我是一名优秀的程序员,十分优秀!