垃圾回收
什么是垃圾回收?
垃圾回收是一种机制,它使计算机能够检测到对象何时不能再被访问。然后它自动释放该对象所使用的内存(同时调用由用户编写的称为“终结程序”的清理例程)。有些垃圾回收器(如 .NET 使用的垃圾回收器)压缩内存,从而减小程序的工作集。
返回到顶部
非确定性的垃圾回收如何影响代码?
对于大多数程序员而言,拥有垃圾回收器(并使用垃圾回收对象)意味着即使使用复杂的数据结构,也不必担心释放内存或引用计数对象。但是,如果您通常在释放对象内存的同一代码块中释放系统资源(文件句柄、锁等等),则确实需要在编码样式方面进行某些更改。对于垃圾回收对象,应提供一种以确定方式(即受程序的控制)释放系统资源的方法,并使垃圾回收器可以在压缩工作集时释放内存。
返回到顶部
可以避免使用垃圾回收堆吗?
所有面向运行库的语言都允许从垃圾回收堆分配类对象。这带来了快速分配方面的好处,并且使程序员不必计算出何时应显式“释放”每个对象。
CLR 还提供所谓的 ValueType。ValueType 与类相似,不同的是 ValueType 对象在运行时堆栈(而不是堆)上分配,因此当代码退出定义了这些对象的过程时它们将被自动回收。这便是 C# 中“结构”的操作方式。
C++ 托管扩展使您可以选择分配类对象的位置。如果由 __gc 关键字声明为托管类,则它们从垃圾回收堆中分配。如果它们不包括 __gc 关键字,则它们的行为和常规 C++ 对象类似,都是从 C++ 堆分配,并且由“free”方法显式释放。
有关垃圾回收的附加信息,请参阅:
- 垃圾回收:Microsoft .NET 框架中的自动内存管理
- 垃圾回收(第 2 部分):Microsoft .NET 框架中的自动内存管理
返回到顶部
远程处理
进程内和进程间通讯在公共语言运行库中的工作机制是什么?
进程内通讯有两个方面:单个应用程序域中的上下文之间的通讯或应用程序域之间的通讯。在同一应用程序域的上下文之间,代理用作侦听机制。不涉及任何封送处理或序列化操作。在跨越多个应用程序域时,我们使用运行时二进制协议进行封送处理/序列化。
进程间通讯使用可插接式信道和格式化程序协议,其中每个协议适用于特定的目的。
- 如果开发人员使用工具 soapsuds.exe 指定端点以生成元数据代理,则默认设置为具有 SOAP 格式化程序的 HTTP 信道。
- 如果开发人员在托管环境中进行显式的远程处理,则必须明确要使用的信道和格式化程序。这可以表示为管理形式,通过配置文件,或通过 API 调用加载特定的信道。选项为:
具有 SOAP 格式化程序的 HTTP 信道(HTTP 非常适合在 Internet 上使用或者通讯必须经过防火墙的情况)
具有二进制格式化程序的 TCP 信道(TCP 是用于局域网 (LAN) 的性能更高的选项)
当在托管代码和非托管代码间进行转换时,COM 结构(确切地说是 DCOM)用于远程处理。在 CLR 的中间版本中,这通过适用于被服务的组件(使用 COM+ 服务的组件)。在最终发布时,应该可以配置任何可远程处理的组件。
对象的分布式垃圾回收由称为“基于租约的生存期”的系统托管。每个对象均有一个租用时间,当时间过期时,对象会与 CLR 的远程处理结构断开连接。对象都有默认的续订时间,当从客户端成功地调用了对象时续订该租约。客户端也可以显式续订租约。
返回到顶部
互操作性
可以在 .NET 框架程序中使用 COM 对象吗?
可以。现已部署的任何 COM 组件均可通过托管代码中使用,通常情况下,改编是完全自动的。
具体说来,自动行为是使用运行库可调用的包装 (RCW) 从 .NET 框架访问 COM 组件。该包装将 COM 组件公开的 COM 接口转换成与 .NET 框架兼容的接口。对于 OLE 自动化接口,RCW 可以从类型库中自动生成。而对于非 OLE 自动化接口,开发人员可以编写自定义 RCW,并将 COM 接口公开的类型手动映射至与 .NET 框架兼容的类型。
返回到顶部
可以在 COM 程序中使用 .NET 框架组件吗?
可以。现已生成的托管类型可通过 COM 访问,通常情况下,配置是完全自动的。托管开发环境的某些新功能无法通过 COM 访问。例如,静态方法和参数化构造函数无法通过 COM 使用。通常情况下,最好提前确定给定类型的预期用户。如果要通过 COM 使用类型,则可能只限于使用 COM 可访问的功能。
根据用于编写托管类型的语言,默认情况下,该类型可能是可见的,也可能是不可见的。
具体说来,自动行为是使用 COM 可调用的包装 (CCW) 从 COM 访问 .NET 框架组件。这与 RCW 类似(请参阅前一个问题),但工作方向相反。此外,如果 .NET 框架开发工具无法自动生成包装,或者如果自动行为不是您所要的,则可以开发自定义 CCW。
返回到顶部
可以在 .NET 框架程序中使用 Win32 API 吗?
可以。使用平台调用,.NET 框架程序可以通过静态 DLL 入口点访问本机代码库。
下面是一个调用 Win32
MessageBox 函数的 C# 示例:
using System; using System.Runtime.InteropServices; class MainApp { [DllImport("user32.dll", EntryPoint="MessageBox")] public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType); public static void Main() { MessageBox( 0, "Hello, this is PInvoke in operation!", ".NET", 0 ); } }
返回到顶部
安全性
为使代码适用于安全系统,必须做哪些工作?
这通常不是问题,大多数应用程序将安全运行,并且不会被恶意攻击所利用。只需使用标准的类库访问资源(如文件)或执行受保护的操作(如类型的私有成员反射),安全性便由这些库得到加强。开发人员可能需要做的一件简单的事是包括权限请求(声明安全性的形式),以限制代码可以接收的权限(限制为它需要的权限)。这还可确保在允许代码运行的情况下,只有具备了所需的所有权限才能这样做。
只有编写新基类库公开新的资源类型的开发人员才需要直接使用安全系统。不是使所有的代码都有潜在的安全危险,代码访问安全性将危险限制在显式重写安全系统的极少量代码上。
返回到顶部
为什么在从网络共享驱动器运行代码时收到安全性异常?
默认的安全策略只向来自本地 Intranet 区域的代码授予一组有限的权限。该区域由 Internet Explorer 安全设置定义,并且应配置为与企业中的本地网络匹配。由于由 UNC 或映射驱动器命名(如用 NET USE 命令)的文件通过该本地网络发送,这些文件也在本地 Intranet 区域中。
默认值是针对不安全 Intranet 的最坏情况设置的。如果您的 Intranet 比较安全,则可以修改安全策略(用 .NET 框架配置工具或 CASPol 工具),向本地 Intranet 或它的各部分(例如特定的计算机共享名称)授予更多权限。
返回到顶部
如何使代码在安全系统停止它时运行?
当代码试图执行无权执行的操作时会发生安全性异常。权限的授予基于已知的代码情况,尤其是它的位置。例如,从 Internet 运行的代码比从本地计算机运行的代码获得的权限少,因为经验证明前者通常不如后者可靠。因此,为了使因安全性异常而失败的代码运行,必须增加授予它的权限。这样做的一个简单方法是将代码移至更受信任的位置(如本地文件系统)。但这并不适用于所有情况(Web 应用程序便是一个很好的例子,公司网络上的 Intranet 应用程序是另一个例子)。因此,如果不改变代码的位置,还可以更改安全策略,向该位置授予更多权限。使用 .NET 框架配置工具或代码访问安全策略实用工具(caspol.exe)都可以做到这一点。如果您是代码开发人员或发布者,则还可以