在运维工作中,经常能接到客户的反馈这个:引发类型为“System.OutOfMemoryException”的异常。客户反馈物理内存都还有富余,怎么报内存不足的错误呢!

什么时候会引发System.OutOfMemoryException:操作系统无法满足GC对连续内存块的请求,则会发生System.OutOfMemoryException

可能原因
1:内存真的不够了,连虚拟内存都用完了。
2:内存还有,但碎片化严重,无法找到合适的连续内存块。

一些常见的原因
1、系统里缓存了大量的数据,没有及时释放。应该控制缓存的数据大小,缓存失效的时间。
2、操作的大数据的文件或者DataTable。应该分块读取。
3、本地资源泄漏。
解决方案:
3.1 应该及时释放本地资源
3.2 使用IDisposable模式

4、大量的对象被固定,不能被压缩移动,导致内存产生大量碎片。
解决方案:

4.1 如果固定对象大约在同一时间分配,则每两个对象之间的碎片更小
4.2 优先初始化,因为较旧的对象位于堆的底部,但大多数可用空间都是在堆顶部生成的。
4.3 固定对象的时间越短,GC就越容易压缩堆

测试环境:物理内存8G,64位操作系统
示例一、物理内存,虚拟内存都被消耗完,抛出System.OutOfMemoryException的异常

using System;
using System.Collections.ObjectModel; namespace OutOfMemoryExample
{
class Program
{
static List<byte[]> _root = new List<byte[]>();
static void Main(string[] args)
{
try
{
int i = ;
while (true)
{ var smallObject = new byte[ * ];//小于85000byte的对象存在小对象堆(SOH – small object heap)
Console.WriteLine(string.Format("{0}K", i * ));
_root.Add(smallObject);//用静态List对象不断新增小对象,由于静态对象不会被回收,最终会发现物理内存和虚拟内存都耗尽,抛出OutOfMemory异常
i++;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
} Console.Read();
} }
}
}

示例二、物理内存还有4G,虚拟内存都被消耗完(22G),

大对象(大于85000byte)存储到大对象堆,大对象堆属于第二代堆,垃圾回收时不会压缩内存,分配一个大对象时,优先尝试在大对象堆的尾部进行分配,如果尾部空间不足,就会尝试向操作系统请求更多的内存空间,

前面都失败失败时,才会重新搜索之前无效对象留下的内存空隙。如果没有找到连续的内存块,抛出System.OutOfMemoryException的异常。

疑问:为什么物理内存还有,大对象堆为什么向操作系统申请不到内存?

我推测是这些剩余的内存被一些程序给预留了,或者没有大的内存块。

using System;
using System.Collections.ObjectModel; namespace OutOfMemoryExample
{
class Program
{
static List<byte[]> _root = new List<byte[]>();
static void Main(string[] args)
{
try
{
for(int i=1;i<500000;i++)
{ var largeObject = new byte[100 * 1024];//大于85000byte的对象存在一个大对象堆(LOH –large object heap)
Console.WriteLine(string.Format("第{0}次:{1}K",i, i * 100));
_root.Add(largeObject);//用静态List对象不断新增对象,由于静态对象不会被回收,最终会发现虚拟内存都耗尽,抛出OutOfMemory异常!但物理内存还有4G
i++;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
} Console.Read();
} }
}

  

最新文章

  1. lower函数
  2. SQL Developer报错:Unable to find a Java Virtual Machine解决办法
  3. jQuery实现全选、全不选、反选
  4. 取消GridView/ListView item被点击时的效果 记录学习
  5. ios中通过调试来使用私有api
  6. 【&lt;td&gt;】使&lt;td&gt;标签内容居上
  7. EDM推送
  8. 389. Find the Difference
  9. apktool 反翻译错误
  10. STL-multimap
  11. Caused by: org.springframework.beans.NotWritablePropertyException
  12. none 和 host 网络的适用场景 - 每天5分钟玩转 Docker 容器技术(31)
  13. ASP.NET Core Web API 最小化项目
  14. window、linux系统与linux服务器之间使用svn同步及自动部署代码的方法
  15. New FileReader上传图片
  16. Android Studio 1.0RC1版发布
  17. PHP 利用PHPExcel 文件导入(也可保存到本地或者服务器)、导出
  18. C++ 值传递、指针传递、引用传递详解
  19. 微信emoji表情编码 、MySQL 存储 emoji 表情符号字符集
  20. 断开网络连接的dos命令

热门文章

  1. Delphi : keydown与keypress的区别,组合键
  2. 使用docker部署项目
  3. bzoj1036 [ZJOI2008]树的统计Count(树链剖分)
  4. 多进程编程之守护进程Daemonize
  5. BZOJ3162 独钓寒江雪(哈希+树形dp)
  6. 十三个有彩蛋的Linux命令
  7. IbatisNet连接oracle 报错
  8. [LOJ3049] [十二省联考 2019] 字符串问题
  9. [洛谷P5081]Tweetuzki 爱取球
  10. BZOJ3155:Preprefix sum——题解