如何解决内存溢出以及内存泄漏

Posted 夏雨_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何解决内存溢出以及内存泄漏相关的知识,希望对你有一定的参考价值。

前言:

很多人在项目中都遇到过内存溢出问题,其实说白了就是内存不够用了,那么要解决这个问题,我们就需要 “开源节流”了

1.开源(增加内存分配)

每台手机给每个程序分配的内存都是固定的,那么是否有办法使我们的程序获取到更大的内存呢?其实是有的,而且很简单

你只需要在清单文件中的application的节点中加入 android:largeHeap=”true” 即可, 是不是很简单?

<application
      ...
        android:largeHeap="true"
       >

    </application>

但是这样做其实是有弊端的,google虽然暴露了这个方法,但是他本身是不建议这样设置的,以下是google的描述:

However, the ability to request a large heap is intended only for a small set of apps that can justify the need to consume more RAM
 (such as a large photo editing app). Never request a large heap simply because you’ve run out of memory and you need a quick fix
—you should use it only when you know exactly where all your memory is being allocated and why it must be retained. Yet, even 
when you’re confident your app can justify the large heap, you should avoid requesting it to whatever extent possible. Using the
 extra memory will increasingly be to the detriment of the overall user experience because garbage collection will take 
longer and system performance may be slower when task switching or performing other common operations.

其实这样设置主要是会有三个问题

  • 1.由于内存变大导致GC花费的时间更长,一旦跟不上Android屏幕刷新的速度,可能会有一定的视觉残留
  • 2.内存越大,在后台的时候越容易被回收
  • 3.对于手机来说,单个app占用的内存越大,整体体验感就越不好

所以笔者认为,不是特别需要内存的app,不应该通过largeHeap来提高分配的内存,而是应该通过内存优化方面来减少内存的使用

2.节流(内存优化)

说到内存优化,要讲的东西就多了,但是其中效果最明显的就是以下两点

  • 1.图片显示的优化
  • 2.解决内存泄漏

2.1 图片显示的优化

在安卓手机上显示一张图片占用的内存,和这张图片本身的大小并没有直接关系,他主要看的是图片像素以及图片的色彩格式;

不做处理的情况下,加载一张4000 * 2000(一般手机拍摄的都超过这个像素)的图片,需要占用的内存为:

4000 * 2000 * 4 / 1024 / 1024 = 30 (MB)

也就是说只要同时加载几张图片,你的应用就会OOM(内存溢出了),最恐怖的是就算你的ImageView的宽高只有10px,同样会占用那么多内存

所以这就是为什么图片显示的优化的效果那么明显

具体如何对图片进行压缩,就要具体结合你使用的显示方法,是直接显示,还是通过Picasso,或者是通过Glide,这里可以参考这篇博客

图片的压缩

http://blog.csdn.net/yulyu/article/details/55215718


2.2 内存泄漏

内存泄漏,说白了就是有些资源被占用了,使得他们没有及时得到回收

常见的内存泄漏发生在以下几种情况

  • 1.activity或fragment被静态持有了
  • 2.handler的使用,在activity销毁时,handler的任务还在执行中
  • 3.一些监听没有移除,或者类似观测者等只做了注册,没有在销毁时注销

虽然我们现在知道了哪些情况下会发生内存泄漏了,但是我们如何知道自己的程序是否存在内存泄漏问题呢?其实有很多工具可以帮助我们分析

  • 1.LeakCanary
  • 2.Android Studio 的 Monitors

LeakCanary是很多博客里面推荐的内存泄漏检测神器,确实挺不错的,但是笔者更喜欢用Android Studio自带的Monitors,因为不用任何代码和插件,操作起来也更方便,下面就简单介绍一下这个工具的使用了


2.3 Monitors的使用

(1)在Android Studio底部,点击图中控件,就会开始分析(需要等待一段时间,项目较大的话可能要一分钟)

(2)在分析完毕后会生成一个hprof文件,并弹出.按照下面图片的操作就能看到内存泄漏的位置

完整gif如下:

这里模仿的是SecondActivity被静态持有导致的内存泄漏,模拟代码如下,上面的图片中可以很明显的看出是SecondActivity的mContext导致的内存泄漏

public class SecondActivity extends AppCompatActivity 

    public static Context mContetx;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        setContext(this);
    

    private static void setContext(Context context) 
        mContetx = context;
    



2.4 其他

在个别手机中(比如三星note3),LeakCanary和Monitors的检测有一点问题,他们都一定会检测到你的第一个activity内存泄漏,这有可能是因为厂商修改了源码导致的

热门文章

以上是关于如何解决内存溢出以及内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

JVM之内存泄漏和内存溢出

内存溢出和内存泄漏的区别,产生原因以及解决方案

内存溢出和内存泄漏的区别,产生原因以及解决方案

内存溢出和内存泄漏的区别产生原因以及解决方案 转

如何定位和解决Android的内存溢出问题(大总

如何防止java中的内存泄漏