OOM

1.什么叫OOM,out of memory的简称,称之为内存溢出;

2.JVM内存模型

    按照JVM规范,JAVA虚拟机在运行时会管理以下的内存区域:

    程序计数器:当前线程执行的字节码的行号指示器,线程私有;
    JAVA虚拟机栈:Java方法执行的内存模型,每个Java方法的执行对应着一个栈帧的进栈和出栈的操作。
    本地方法栈:类似“ JAVA虚拟机栈 ”,但是为native方法的运行提供内存环境。
    JAVA堆:对象内存分配的地方,内存垃圾回收的主要区域,所有线程共享。可分为新生代,老生代。
    方法区:用于存储已经被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。Hotspot中的“永久代”。
    运行时常量池:方法区的一部分,存储常量信息,如各种字面量、符号引用等。
    直接内存:并不是JVM运行时数据区的一部分, 可直接访问的内存, 比如NIO会用到这部分。

    按照JVM规范,除了程序计数器不会抛出OOM外,其他各个内存区域都可能会抛出OOM。

3. 最常见的OOM情况有以下三种:

    java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设  置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。


    java.lang.OutOfMemoryError: PermGen space ------>java永久代溢出,即方法区溢出了,一般出现于大量Class或者jsp页面,或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。

java.lang.StackOverflowError ------> 不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。

4.OOM问题,原因不外乎以下3类

    1、线程池不管理式滥用

    2、本地缓存滥用(如只需要使用Node的id,但将整个Node所有信息都缓存)

    3、特殊场景考虑不足(如采用单线程处理复杂业务,环境震荡+多设备下积压任务暴增)

5.而造成OOM的情况大致可以归为以下几类:

    A.  资源对象没关闭造成的内存泄露,try catch finally中将资源回收放到finally语句可以有效避免OOM。资源性对象比如:
       A01,Cursor
       A02,调用registerReceiver后未调用unregisterReceiver()
       A03,未关闭InputStream/OutputStream
       AO4,Bitmap使用后未调用recycle()

   B. 作用域不一样,导致对象不能被垃圾回收器回收,比如:
       B01,非静态内部类会隐式地持有外部类的引用,
       B02,Context泄露,概括一下,避免Context相关的内存泄露,记住以下事情:
             1、 不要保留对Context-Activity长时间的引用(对Activity的引用的时候,必须确保拥有和Activity一样的生命周期)
             2、尝试使用Context-Application来替代Context-Activity;

             3、如果你不想控制内部类的生命周期,应避免在Activity中使用非静态的内部类,而应该使用静态的内部类,

             并在其中创建一个对Activity的弱引用。
             这种情况的解决办法是使用一个静态的内部类,其中拥有对外部类的WeakReference。

       B03,Thread 引用其他对象也容易出现对象泄露。
       B04,onReceive方法里执行了太多的操作
   C.内存压力过大
       C01,图片资源加载过多,超过内存使用空间,例如Bitmap 的使用
       C02,重复创建view,listview应该使用convertview和viewholder

6. 处理方法

   1.使用缓存技术,比如LruCache、DiskLruCache、对象重复并且频繁调用可以考虑对象池
   2.对于引用生命周期不一样的对象,可以用软引用或弱引用SoftReferner WeakReferner
   3.对于资源对象 使用finally 强制关闭
   4.内存压力过大就要统一的管理内存

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值