防止.NET应用程序内存溢出(OOM)的一些措施

批量和分页

  在典型的互联网web应用中,数据量较大且高并发的情况下,不分页,或者不进行批量处理,每次总是取出很多用户数据,很容易造成内存开销过大,系统内存吃紧。再比如我们有时候进行文件操作,读取文件内容的时候就要斟酌考虑文件有多大。

慎用静态

  比起大数据查询造成的常发性的内存不足,使用静态太多的应用程序一时半会也不会内存泄露。可随着系统的运行,静态的东西越来越多,内存开销也就越大,由于GC的回收策略,无效的静态所占内存又不容易及时释放,久而久之就造成了内存不足。

二方库、三方库,非托管资源,优先使用Dispose模式

  每次调用别人的资源都应该有个警觉性:用你的类库可以,占用我的(内存)不行。
  如果你熟悉自动内存管理,熟悉GC,理解Dispose模式,那么一定会在调用别人的资源的时候想着还是using一下为妙,或者,强制赋个null也是举手之劳,要相信某些良好的编程习惯可以让自动内存管理更有效。

减少字符串临时对象

  举例来说,对于String的+=,很多应用程序中这个操作层出不穷。我们都知道+=操作会造成很多临时字符串对象,这些对象由于CLR对字符串的驻留处理,容易占用内存空间。如果是高并发的web应用程序,而字符串操作随处可见,且字符串的长度又不确定地长,前端页面各种各样的拼接,久而久之,内存占用就会是一个重大问题。CLR对字符串的优化处理使得字符串不被优先回收,如果字符串操作频繁,临时字符串较长(比如大于等于85000字节)而出现大对象堆的分配,那么更容易出现内存泄露。
  很多人可能都会想到如何优化程序去降低string的临时对象的生成概率。对的,StringBuilder的出现就顺理成章了。

警惕大对象

  1、任何大于等于85000字节的对象都被自动视为大对象,大对象从特殊的大对象堆中分配。大对象堆和小对象堆一样进行终结和释放,但是GC回收算法从来不对大对象堆(Large Object Heap)进行内存压缩整理,因为在堆中下移85000字节或更大的内存块会浪费太多的CPU时间;
  2、在.NET中,CLR采用基于代(generation)的垃圾回收,大对象总被认为是第2代(generation)的一部分,GC分析哪些对象不可达,优先分析第0代和第1代,第2代的对象通常被认为长时间存活。
  正是由于1和2所述的两个原因(主要原因还是第1个),在垃圾回收过程中容易造成内存碎片。这里推荐一篇老外写的流传甚广的文章供参考:the dangers of the LOH。
  随着应用程序的运行,如果LOH导致的内存碎片越来越多,内存有效使用率下降会非常严重,比如我们在web应用程序中+=拼接字符串(见第4条的分析),如果大于等于85000字节的字符串临时对象很多,那么用户量一上去,随着系统的运行,GC回收压力越来越大OOM的风险会变得更高。
  虽然内存碎片化导致的OOM看上去似乎无解,但是如果写程序的人仔细分析解决问题,想方设法主动降低创建大对象的频率,那么内存泄露的可能就会降低,足够优秀健壮的程序不能彻底解决OOM,但是我们完全可以将风险发生的情况将至最低可能。
  一个足够合格的coder肯定需要具备充足的分析和解决OOM问题的准备和经验,有很多分析和检查OOM的工具如ANTS Memory Profiler,还可以通过调试利器如windbg对内存dump文件进行分析。用好这些工具,让OOM无所遁形也不失为解决之道。

时间: 2024-10-17 22:50:14

防止.NET应用程序内存溢出(OOM)的一些措施的相关文章

内存溢出(Oom)和内存泄露(Memory leak)

内存溢出(Oom):运行内存大于可用内存的情况.比如申请了一个integer空间,结果存放下了只有long才能存放的数据 内存泄露(Memory leak):程序员忘记释放已用内存的情况,是内存管理较为常见的现象 以发生的方式来分类,内存泄漏可以分为4类: 1. 常发性内存泄漏.发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏. 2. 偶发性内存泄漏.发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生.常发性和偶发性是相对的.对于特定的环境,偶发性的也许就变成了常发性

内存溢出OOM

1, OutOfMemoryError异常 除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能, javaHeap 溢出 一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常. 出现这种异常,一般手段是先通过内

记一次java程序内存溢出问题

一个自然语言处理程序,在封装为web-service后,部署到线上运行. 但最近出现了内存溢出的情况,频繁的out of memory. 先盲目尝试在启动脚本中增加-XX:-UseGCOverheadLimit. 因为根据原因未找到,依然频繁的out of memory,只能一直观察jstat -gcutil <pid>,看到老生代内存降不下来时,重启程序. 服务程序很简单,简单接收参数,自然语言处理,返回数据,除了自然语言处理模块,都是方法参数,不会出现内存泄漏的情况. 第一次解决这种内存溢

java常见内存溢出(OOM)

jvm内存区域 程序计数器一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. java栈与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同.通常存放基本数据类型,对象引用(一个指向对象起始地址的引用指针或一个代表对象的句柄),reeturnAddress类型(指向一条字节码指令的地址) 栈区域有两种异常类型:如果线程请求的栈深度大于虚拟机所允许的深度,将抛StrackOverflowError异常:如果虚拟机栈可以动态扩展(大部分虚拟机都可动态扩展),当扩展

bitmap 内存溢出OOM的解决办法分享

昨天遇到这个问题就是从一个输入流里调用BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri))得到一个bitmap报的错.第一次调用都没问题,第二次再次调用就会报上面那个内存溢出的问题.而且有的手机报有的手机不报.研究了半天终于解决.首先分析了下原因,应该是图片占用的内存超过了系统虚拟机可分配的最大限制.不同手机可能分配的最大值不一样.后来找到解决办法主要是设置BitmapFactory.Options.

android 内存溢出OOM问题

好久没有进cnblogs了,都快长草了.之前对接某度要求我司的插件 monkey test满8小时无OOM 无crash 虐哭了...各种OOM 下面把当时写的一篇笔记po上来防止长草. 1.什么是OOM,为什么会有OOM Android主要应用在嵌入式设备中,所以因为嵌入式设备本身的一些限制,通常内存都会比较有限.JAVA拥有自己的一套垃圾回收机制,但并不是说用java编写的程序就不会程序溢出.java运行在虚拟机中,虚拟机在初始化时会给它的对内存(Heap)设置一个上限值,android中这

viewPager--viewpager时,发生内存溢出OOM问题

两个问题:1.如果图片达到500kb每张,你这个划屏会有顿卡:2.快速滑动有出现0.几秒的白屏.图片越大,顿卡越明显. 回复parcool:500kb的背景算大的了,如果是想做图片墙,viewpager不适合,可以使用开源的图片墙工具,内存+硬盘缓存 还有哦,你这个图片根本没有手动回收,依然会OOM! 今天在制作应用某个功能的引导页时,使用了ViewPager进行页面切换,每个页面就放了一个ImageView,使用背景图来进行展示,由于多图(11张)的原因,导致了OOM问题,这里总结一下. 代码

android图片加载内存优化方法,有效解决大图片内存溢出(oom)

低内存的手机如果直接加载大图片,往往会出现OOM的情况.即便是主流手机,也不能无限制的加载大图片.所以在显示图片之前,需要对图片处理,把图片缩放为最合适的尺寸再显示. 网上很大方法都是不管三七二十一,直接压缩图片.这样可能会导致图片失真,显示模糊.我采用的方式是,显示尺寸有多大,就等比例压缩成多大尺寸的图片,关键关于在于如何寻找最合适的尺寸,下面分享两个关键方法,提取至google开源框架volley private static int getResizedDimension(int maxP

使用ViewPager时,发生内存溢出OOM问题

今天在制作应用某个功能的引导页时,使用了ViewPager进行页面切换,每个页面就放了一个ImageView,使用背景图来进行展示,由于多图(11张)的原因,导致了OOM问题,这里总结一下. 代码如下: public class GuideActivity extends Activity implements OnPageChangeListener{ private ViewPager viewPager; private GuideAdapter adapter; private Line