.Net 内存溢出(System.OutOfMemoryException)的常见情况和处理方式总结
https://blog.csdn.net/hliq5399/article/details/51483579
在什么情况下会出现OutOfMemonryException呢? 在我们试图新建一个对象时,而垃圾收集器又找不到任何可用内存时被抛出,这种情况下我们是可以捕获该异常的; 另一种情况是,CLR需要内存时,而却系统却不能提供,也会抛出该异常. 但此时,我们的应用程序是不能捕获该错误的.
内存溢出(OutOfMemoryException)的调试分析
32位操作系统的寻址空间是4G,其中有2G被操作系统占用,也就是说留给用户进程的内存只有2G(其中还要扣除程序加载时映像占用的部分空间,一般只有1.6G~1.8G左右可以使用)。 如果进程运行中需要申请内存,而操作系统无法为其分配内存空间,则会产生内存不足的异常,在.net中为System.OutOfMemoryException(The exception that is thrown when there is not enough memory tocontinue the execution of a program.)。 虽然最终的表现都为OutOfMemoryException,但其产生的原因可能是不一样的,动手解决此问题之前需要先对进程当前内存的使用状态进行分析,找出正确的原因,才能对症下药。下面分享一下调试此类问题的一些心得。
更多内容请参考:http://blog.csdn.net/lazyleland/article/details/6704661
iis应用程序池 内存溢出错误 System.OutOfMemoryException
在ASP.NET Web服务器上,ASP.NET所能够用到的内存,通常不会等同于所有的内存数量。在machine.config配置文件中,配置节<processModel>中有一个属性“memoryLimit”,这个属性的值是一个百分值,默认为“60”,即指定了ASP.NET进程(在任务管理器中大家就可以看到ASP.NET的进程,IIS5中为aspnet_wp,IIS6中为w3wp)能够使用所有物理内存的60%。当ASP.NET使用的内存量超过这个限额时,IIS会开始自动回收(recycle)进程,即创建一个新的进程去负责应付Http请求,而将旧进程所占用的内存回收。
当我们有一台很大内存的服务器时,“memoryLimit”这个值是需要进行适当的调整的。比如我们准备了一台chemas-microsoft-com ffice marttags" />t="on">4G内存的服务器,那么t="on">4G×60%=t="on">2.4G。但是,对于Win32操作系统,一个进程所能占用的所有内存空间只有t="on">2G。当ASP.NET进程占用的内存开始达到t="on">2G时,由于它并没有达到t="on">2.4G的“回收阈值”,所以IIS不会启动recycle进程操作,但是由于Win32的限制,实际上已经不能给这个进程分配更多的内存了,于是,OutOfMemoryException就很可能会被抛出了。为了避免这样的情况,我们就必须将“memoryLimit”适当调小,以让IIS更早的进行进程回收。
微软推荐的ASP.NET进程占用内存是不超过60%,并最好使计算出的实际值不超过t="on">800M。就是说,对于一台t="on">4G内存的服务器,最好将“memoryLimit”属性设置成“20”。设置一个适当的回收阈值,让IIS适时的进行进程回收,对于保证整个服务器的稳定运行,避免OutOfMemoryException是非常重要的。
在IIS6中,ASP.NET进程的回收阈值不再由配置节中的“memoryLimit”属性决定,而是由IIS管理器中的应用程序池配置中的设置决定。
但是,即使正确设置了这些配置,也不能保证完全避免OutOfMemoryException的发生,原因可能是多样而复杂的,比如内存回收操作可能耗时太多等等。开发人员要注意的,就是在代码中时刻牢记不要无谓的使用和浪费内存。:)
如果你有一台大内存的服务器,同时对Win32操作系统中对于进程最高使用t="on">2G内存的限制很郁闷,可选的解决方法有两个:
- 使用/3GB模式启动计算机,方法参加文后的链接
- 使用Windows Server 2003 64bits Edition
避免内存溢出的几点要素
如果要创建数组,请确保其大小正确。
确保有足够的内存用于内部用途和新的托管对象。
如果您正在 .NET Compact Framework 上进行编程,当没有足够的内存可用于内部用途或新的托管对象时,公共语言运行库会引发此异常。要避免此异常,应避免编写占用 64KB 或更多内存的大方法。
过多的托管内存使用量通常由以下因素造成:
- 将大型数据集读入内存中。
- 创建过多的缓存条目。
- 上载或下载大文件。
- 在分析文件时过多地使用正则表达式或字符串。
- 过多的视图状态。
- 会话状态中有过多的数据或者会话过多。
- 当对 COM 对象调用一个方法,并且该方法返回包含安全数组(大小不固定的数组)的用户定义类型时,可能引发此异常,并附带一条额外的消息“存储空间不足,无法完成此操作”。这是因为 .NET Framework 无法封送带有安全数组类型的结构字段。
一种不当使用字节数组导致内存溢出的情况举例
-
public partial class _Default : System.Web.UI.Page
-
{
-
protected void Page_Load(object sender, EventArgs e)
-
{
-
byte[] bytes = File.ReadAllBytes("D:\toClient.xls");//toClient.xls 大小为20M
-
Response.BinaryWrite(bytes);
-
}
-
}
上面的程序如果所输出的文件特别大的话,有可能会直接报:System.OutOfMemoryException。正确的做法是把文件的字节流分段输出,其实asp.net有现成的方法Response.WriteFile(filePath)就是这么做的。
如下是正确的写法:
-
Response.ContentType = "application/octet-stream";
-
Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(downloadName, System.Text.Encoding.UTF8));
-
Response.WriteFile("D:\toClient.xls");
-
Response.Flush();
-
Response.End();
当asp.net出现内存溢出时,一种简单的处理方法是马上回收应用程序池。但是这样并没有彻底解决问题。
创建Image类型时出现内存溢出(System.OutOfMemoryException)
错误代码: System.Drawing.Image myimg=System.Drawing.Image.FromFile(file.FullName);
当打开的文件不是图像文件时会引发的异常:
MSDN:如果文件没有有效的图像格式,或者如果 GDI+ 不支持文件的像素格式,则此方法将引发 OutOfMemoryException 异常。
这样的异常信息容易让人误解。
<processModel> 元素
在 Internet 信息服务 (IIS) Web 服务器上配置 ASP.NET 进程模型设置。只能在 Machine.config 文件中设置 <processModel> 节,并且该节影响服务器上运行的所有 ASP.NET 应用程序。
警告 有关此元素的信息,请阅读“注释”部分。
配置结构的示例:
<configuration>
<system.web>
<processModel>
-
<processModel enable="true|false"
-
timeout="hrs:mins:secs|Infinite"
-
idleTimeout="hrs:mins:secs|Infinite"
-
shutdownTimeout="hrs:mins:secs|Infinite"
-
requestLimit="hrs:mins:secs|Infinite"
-
requestQueueLimit="num|Infinite"
-
restartQueueLimit="num|Infinite"
-
memoryLimit="percent"
-
cpuMask="num"
-
webGarden="true|false"
-
userName="username"
-
password="password"
-
logLevel="All|None|Errors"
-
clientConnectedCheck="hrs:mins:secs|Infinite"
-
responseDeadlockInterval="hrs:mins:secs|Infinite"
-
responseRestartDeadlockInterval="hrs:mins:secs|Infinite"
-
comAuthenticationLevel="Default|None|Connect|Call|
-
Pkt|PktIntegrity|PktPrivacy"
-
comImpersonationLevel="Default|Anonymous|Identify|
-
Impersonate|Delegate"
-
maxWorkerThreads="num"
-
maxIoThreads="num"/>
可选的属性
属性 选项 描述
clientConnectedCheck | 指定在 ASP.NET 检查连接的客户端之前,请求在队列中存在多长时间。 | |
comAuthenticationLevel | 为 DCOM 安全指定身份验证级别。默认值为 Connect。 | |
Default | 指定 DCOM 使用其正常的安全协商算法来确定身份验证级别。 | |
None | 指定不进行身份验证。 | |
Connect | 指定仅当客户端建立与服务器的关系时,DCOM 才对客户端凭据进行验证。 | |
Call | 指定在每个远程过程调用开始时服务器收到请求的时候,DCOM 对客户端凭据进行验证。 | |
Pkt | 指定 DCOM 验证收到的所有数据是否均来自预期的客户端。数据报传输始终使用 Pkt 身份验证。 | |
PktIntegrity | 指定 DCOM 验证在客户端和服务器之间传输的数据是否未被修改。 | |
PktPrivacy | 指定 DCOM 验证所有先前的级别并加密每个远程过程调用的参数值。 | |
comImpersonationLevel | 指定 COM 安全的身份验证级别。 | |
Default | 指定 DCOM 使用其正常的安全协商算法来确定模拟级别。 | |
Anonymous | 指定客户端对服务器是匿名的。服务器可以模拟客户端,但模拟令牌不包含任何信息。在版本 1.1 中不支持 Anonymous。 | |
Identify | 指定服务器可以获取客户端的标识。服务器可以模拟客户端以进行访问控制列表 (ACL) 检查,但它不能作为客户端访问系统对象。 | |
Impersonate | 指定服务器进程在代表客户端操作时可以模拟客户端的安全上下文。可以使用此级别的模拟来访问本地资源,如文件。在此级别进行模拟时,只能在一个计算机边界传递模拟令牌。 | |
Delegate | 指定服务器进程在代表客户端操作时可以模拟客户端的安全上下文。在使用掩饰代表客户端操作时,服务器进程也可以对外调用其他的服务器。在其他计算机上,服务器可以作为客户使用客户端的安全上下文访问本地和远程资源。在此级别进行模拟时,可以在任意数量的计算机边界传递模拟令牌。 | |
cpuMask | 指定多处理器服务器上的哪些处理器可以运行 ASP.NET 进程。cpuMask 值指定一种位模式,它指示 CPU 可以运行 ASP.NET 线程。例如,cpuMask 十六进制值 0x0d 表示位模式 1101。在具有 4 个 CPU 的计算机上,它指示可以将 ASP.NET 进程安排在 CPU 0、2 和 3,但不能安排在 CPU 1 上。ASP.NET 为每个合格的 CPU 启动一个工作进程。如果将 webGarden 属性(参见下面)设置为 true,则 cpuMask 将工作进程限制为合格 CPU 的数量。(工作进程的最大允许数量等于 CPU 的数量。)默认情况下,启用所有的 CPU,并且 ASP.NET 为每个 CPU 启动一个进程。如果将 webGarden 设置为 false,则忽略 cpuMask 属性,并且只运行一个工作进程。 | |
enable | 指定是否启用进程模型。 | |
true | 指示进程模型已启用。 | |
false | 指示进程模型未启用。 | |
idleTimeout | 指定在 ASP.NET 自动结束工作进程之前,工作进程处于不活动状态的时间(采用时:分:秒字符串格式)。默认设置为 Infinite。 | |
logLevel | 指定要记录到事件日志中的事件类型。 | |
All | 指定记录所有的进程事件。 | |
None | 指定不记录任何事件。 | |
Errors | 指定只记录意外关闭、内存限制关闭和死锁关闭。Errors 为默认值。 | |
maxWorkerThreads | 5 - 100 | 配置每个 CPU 上的进程使用的工作线程的最大数量。例如,如果在单处理器服务器上该值为 25,则 ASP.NET 使用运行时 API 将进程限制设置为 25 个。在双处理器服务器上,将该限制设置为 50。默认值为 20。maxWorkerThreads 的值必须大于或等于 <httpRuntime> 配置节中的 minFreeThread 属性设置。 |
maxIoThreads | 5 - 100 | 配置每个 CPU 上的进程使用的 I/O 线程的最大数量。例如,如果在单处理器服务器上该值为 25,则 ASP.NET 使用运行时 API 将进程限制设置为 25 个。在双处理器服务器上,将该限制设置为 50。默认值为 20。maxIoThreads 的值必须大于或等于 <httpRuntime> 配置节中的 minFreeThread 属性设置。 |
memoryLimit | 指定在 ASP.NET 启动新的进程和重新分配现有请求之前,允许工作进程占用的最大内存大小(总系统内存的百分比)。默认值是 60%。 | |
password | 如果给出(与 userName 结合使用),则此属性导致工作进程以配置的 Windows 标识运行。默认值为 AutoGenerate。有关特殊名称 System 和 Machine(它们不需要密码)的详细信息以及在注册表中存储加密工作进程凭据的信息,请参阅 userName。 | |
pingFrequency | 使用标准进程模型格式(时:分:秒)指定时间间隔,ISAPI 扩展按此间隔 ping 工作进程以查看它是否正在运行。如果工作进程在 pingTimeout 间隔内没有运行,则重新启动该工作进程。默认值为 30 秒钟。 | |
pingTimeout | 使用标准进程模型格式(时:分:秒)指定重新启动未响应工作进程之前的时间间隔。ISAPI 扩展每隔 pingFrequency 时间间隔 ping 一次工作进程。如果工作进程在 pingTimeout 间隔内没有响应,则重新启动该进程。默认值为 5 秒钟。 | |
requestLimit | 指定在 ASP.NET 自动启动新工作进程以替换当前进程之前允许的请求数。默认设置为 Infinite。 | |
requestQueueLimit | 指定在 ASP.NET 开始给新请求返回“503 - 服务器太忙”错误之前队列中允许的请求数。默认值是 5000。 | |
responseDeadlockInterval | 使用标准进程模型格式(时:分:秒)指定重新启动工作进程之前的时间间隔(如果满足以下条件):
默认值为 3 分钟。 | |
responseRestartDeadlockInterval | ASP.NET 不再使用此属性,并且仅出于向后兼容性的需要提供此属性。如果它已在配置文件中存在,则它不会引起配置错误。现在,出现死锁情况下的所有回收是由 responseDeadlockInterval 属性控制的。 | |
serverErrorMessageFile | 如果给出,则它指定要使用的文件内容,而不是出现致命错误时给出的默认“服务器不可用”消息。文件位置是与 Machine.config 相对的,也可以是绝对文件路径。如果没有给出该属性,则使用默认的“服务器不可用”消息。 | |
shutdownTimeout | 指定工作进程自行关闭前允许的分钟数。当超时到期时,ASP.NET 就会关闭工作进程。时间用时:分:秒字符串格式表示。默认值为 5 秒钟或 0:00:05。 | |
timeout | 指定在 ASP.NET 启动新工作进程以替换当前进程之前的时间(以分钟为单位)。默认设置为 Infinite。 | |
userName | 如果给出,则 userName 属性使用不同于默认进程标识的 Windows 标识运行 ASP.NET 工作进程。默认情况下,将 userName 设置为特殊值 Machine,并且进程运行使用的用户帐户为 ASPNET(在安装 ASP.NET 时自动创建的)。ASPNET 帐户的密码是在安装时以加密形式生成的。如果在 userName 和 password 属性中给出了有效的凭据,则进程使用给定的帐户运行。userName 的另外一个特殊值为 System,密码为 AutoGenerate(它使用管理员帐户来运行进程,并且允许在此进程下运行的所有 ASP.NET 用户代码具有完全管理权限)。有关在用作域控制器的服务器上使用 ASP.NET 的信息,请参阅下面的“注释”部分。 userName 和 password 以明文形式存储在配置文件中。尽管 IIS 将不会为响应用户代理请求而传输 .config 文件,但是可通过其他方法读取配置文件,例如,通过对包含该服务器的域具有正确凭据的经过身份验证的用户访问。为了维护安全性,processModel 节支持在注册表中存储加密的 userName 和 password 属性。凭据必须采用由 Windows 2000 和 Windows XP 数据保护 API (DPAPI) 加密功能加密的 REG_BINARY 格式。详细信息,请参阅下面的“注释”和“示例”部分。 | |
webGarden | 在与 cpuMask 属性结合使用时控制 CPU 关系。(多处理器 Web 服务器称为“Web 园”。) | |
true | 指示 cpuMask 属性用于指定哪些 CPU 适合运行 ASP.NET 进程。 | |
false | 指示 CPU 的使用是由 Windows 操作系统调度的。忽略 cpuMask 属性并且只运行一个工作进程。默认值是 false。 |
注释
托管代码配置系统并不读取 <processModel> 配置设置。而是由非托管 DLL aspnet_isapi.dll 直接读取。重新启动 IIS 后,本节的更改才会生效。
如果在域控制器上安装 ASP.NET,必须采取特殊的步骤,否则安装无法正常进行。详细信息,请参阅位于 http://support.microsoft.com 的 Microsoft 知识库中的文章 CHS315158“ASP.NET 在域控制器上不能使用默认 ASPNET 帐户”。
当 ASP.NET 在 IIS 版本 6 本机模式下运行时,使用 IIS 6 进程模型并且忽略 <processModel> 节中的设置。要配置进程标识、回收或其他进程模型值,请使用 Internet 服务管理器用户界面为应用程序配置 IIS 工作进程。
时间值的格式为“时:分:秒”。如果只给出单个数字而没有冒号,则假定该值为分钟数;因此 timeout="4" 等同于 timeout="00:04:00"。
如果 ASP.NET 应用程序导致 ASP.NET 工作进程(Windows 2000 和 Windows XP Professional 上的 Aspnet_wp.exe 以及 Windows Server 2003 上的 W3wp.exe)重新启动,并给出一条错误消息,指示重新启动是由于怀疑的死锁状态造成的,则应该增加 responseDeadlockInterval 设置。
在注册表中存储用户名和密码
将用户名和密码存储在注册表中
要加密用户名和密码并将它们存储在注册表中,请按如下方式设置 userName 和 password。
userName="registry:HKLM\Software\AspNetProcess,Name"
password="registry:HKLM\Software\AspNetProcess,Pwd"
关键字 registry 后面、逗号前面的字符串部分表示 ASP.NET 所打开的注册表项的名称。逗号后面的部分包含一个字符串值名,ASP.NET 将从中读取凭据。逗号是必需的,凭据必须存储在 HKLM 配置单元中。如果配置格式有误,则 ASP.NET 将不启动工作进程,并随后出现当前帐户创建失败代码的路径。
凭据必须采用 REG_BINARY 格式,其中包含对 Windows API 函数 CryptProtectData 调用的输出结果。您可以用 ASP.NET设置注册表控制台应用程序 (Aspnet_setreg.exe) 创建加密凭据并将其存储在注册表中,该应用程序使用 CryptProtectData 完成加密。要下载 Aspnet_setreg.exe 以及 Visual C++ 源代码和帮助,请访问网站 www.asp.net 并搜索“aspnet_setreg”。
您应该对存储加密凭据的注册表项配置访问权限,以便只对 Administrators 和 SYSTEM 提供访问。因为该注册表项将由作为 SYSTEM 运行的 ASP.NET 进程读取,您应该设置下列权限:
Administrators:F
SYSTEM:F
CREATOR OWNER:F
ProcessAccount:R
这将提供两道防线来保护数据:
- ACL 权限要求访问数据的标识为 Administrator。
- 攻击者必须在服务器上运行代码 (CryptUnprotectData) 以便恢复帐户的凭据。
示例
以下示例指定几个 <processModel> 配置设置。
-
<configuration>
-
<system.web>
-
<processModel
-
enable="true"
-
timeout="15"
-
idleTimeout="25"
-
shutdownTimeout="5"
-
requestLimit="1000"
-
requestQueueLimit="500"
-
responseDeadlockInterval="00:03:00"
-
responseRestartDeadlockInterval="Infinite"
-
memoryLimit="20"
-
webGarden="true"
-
maxWorkerThreads="25"
-
maxIoThreads="25"/>
-
</system.web>
-
</configuration>
以下示例指定将加密的用户名和密码存储在注册表用户定义的项 AspNetProcess
下面。
-
<configuration>
-
<system.web>
-
<processModel>
-
userName="registry:HKLM\Software\AspNetProcess,Name"
-
password="registry:HKLM\Software\AspNetProcess,Pwd"
-
</processModel>
-
</system.web>
-
</configuration>
要求
- 包含在:<system.web> 中
- Web 平台:IIS 5.0、IIS 5.1、IIS 6.0
- 配置文件:Machine.config、Web.config
- 配置节处理程序:System.Web.Configuration.ProcessModelConfigurationHandler
http://doc.51windows.net/iismmc/?url=/iismmc/htm/aaconprocessmodelelement.htm