内存溢出(oom) :
1.大家应该都知道oom异常是什么吧?对他是因为内存溢出导致的,那你们想过他为什么溢出吗?溢出的原因是什么吗?还有就是既然有垃圾回收机制,可为啥还会有oom异常。(而这就是我接下来要说的重点)
什么是oom(内存溢出):oom就是内存溢出,也就说程序申请的内存过大,vm(虚拟机)无法满足,导致的程序自杀现象,这里我们把他当成一个水杯,原本他的大小是五百毫升,可是你拿六百毫升的水往里面加。而那剩下的一百毫升不就溢出来吗。
1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体;
4.使用的第三方软件中的BUG;
5.启动参数内存值设定的过小
内存溢出的解决方案:
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。
重点排查以下几点:
1.检查对数据库查询中,是否有一次获得全部数据的查询。
一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
2.检查代码中是否有死循环或递归调用。
3.检查是否有大循环重复产生新对象实体。
4.检查对数据库查询中,是否有一次获得全部数据的查询。
一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,
不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
5.检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。
2.而他之所以会溢出来是因为
1.图片过大:
我们一般都是给图片进行压缩而他压缩的方式有:
1.质量压缩(不改变图片的尺寸):先给他设置两个属性bitmap和options:
第一压缩bitmap图片对象
第二给图片保存的位置设置options进行压缩来实现质量压缩。
2.尺寸压缩(可以说是像素压缩):设置采样率,降低像素
3.JNI调用libjpeg库压缩:JNI静态调用bitherlibjni.c的方法实现
4.结合三种方式压缩:1.先进行尺寸压缩(压缩到手机常用的分变率1280*960),然后通过质量压缩来计算options需要设置为多少,最后调用JNI压缩(压缩后的清晰度和原图差不多,所需要的时间大概一秒钟左右)
图片处理:
内存压缩:
1.在内存中压缩图片:给大图片进行压缩,使用等比例压缩方法直接在内存中处理图片
2.使用完图片后回收图片所占的内存
3.降低要显示的图片色彩
三级缓存:内存缓存 优先加载,速度最快, 本地缓存 次优先加载 速度稍快,通过网络获取图片后 保存到本地SD卡中。网络缓存:最后加载 速度由网络速度决定(浪费流量)
主要用到了AsyncTask来进行异步数据的加载
同时,为了避免内存溢出的问题,我们可以在获取网络图片后。对其进行图片压缩
2.界面切换:横竖屏切换多后会导致oom。对于这种问题没有固定解决的方法,只能从几种方面进行分析:
1.查看页面有没有大的图片,就比如背景图之类的
2.直接把XML配置成view然后再放到一个容器里,避免重复加载
3.在切换页面的时候尽可能少用重复代码
3.Bimap对象不再使用时调用recycle()来释放对象
当图片不再用的时候给他调用Bimap.recycle()方法回收这个对象所占的内存空间,但是这也不是必须的(看情况吧)
总之一句话:需要释放的资源在用完之后记得释放对应的资源
2.内存引用:
1.强引用:(最难被Gc回收的)当对象具有强引用的时候,回收机制宁愿抛出OOM,中断程序,也决对不会回收它。
2.软引用:(内存不足GC会回收软引用指向的对象)一个对象具有软引用,只有内存足够回收站就不会回收它
3.弱引用:(不管内存足不足都可能回收弱引用指向的对象)具有弱引用的对象拥有更短的生命周期,不管内存足不足都会回收它的内存
4.虚引用:(该收就收,无所谓这里也叫幽灵引用):可以说是虚设,他不会决定生命周期的对象。如果一个对象
仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
如何释放内存引用:
1.释放强引用:我们使用完对象后,把对象置空。这样我们的垃圾回收机制(gc)就会在合适的时候释放掉该对象
分配的内存空间。
2.释放软引用:我们可以用SoftReference来封装强引用(软引用封装强引用)
3.释放弱引用:我们应该使用WeakReference记住给对象(弱引用封装强引用)
在这里我打个招呼啊:如果我们调用强引用来给他进行封装但是每次都在不用的时候给他进行置空太过麻烦,所以我们一般都给他进行软引用封装
内存泄漏
内存泄漏:当一个对象不用了,原本应该被垃圾回收机制回收。但是却被其他对象所持有,造成无法回收的现象。
(如果泄漏一点的话 没什么关系但是 泄漏的多就导致程序自杀)
这里我就说一个瓶子的话我们先给他放入石头先放一半,剩下的一半全放成土。你会觉得石头间会有多少缝隙
那如果全部放成石头在往里面填土,还能不能加进去,还能加多少。
我就说一下几种常见的问题吧:
1.单例造成的内存泄漏
2.Handler造成的内存泄漏
3.线程造成的内存泄漏
他们几个都有一个相同点那就是引用问题(生命周期长的引用生命周期短的而导致无法被回收)
如何解决:
生命周期长的不要引用生命周期短的context,可以考虑使用application context 替换 activity context
静态变量应该避免引用activity context
3.他们的关系是:内存泄漏是造成内存溢出的主要原因
4.内存溢出:(他会导致崩溃) 内存泄漏:(会引起卡顿,他是一点一点的往外面泄漏,等他泄漏的多的时候就导致崩溃)
大小魔方公式 U2L2F2 U'B2D RF'RF'RF' D'B2U'
六面T字公式 U2 F2 R2 D U' L2 B2 D U或者B2 D2 L R' D2 B2 L R'
说明:把魔方的一面对着你(在做公式的时候保持这个面一直对着你)
将魔方分成上层U 底层D 左层L 右层R 前层F 后层B
L是左层顺时针(以要转动的面为钟面顺时针转)旋转90度 L'是逆时针旋转90度 L2是转180度