Android 内存溢出管理与测试

今天发现正在做的项目,时不时的会报错:dalvikvm heap out of memory on a 7458832-byte allocation (堆分配的内存溢出)

为什么会内存溢出呢?我以前从未遇见这种情况。后来在网上查了查资料,还是挺多的。

怎么说呢?因为Android开发基本上是以java语言为基础,那么程序是在java虚拟机上运行的。而虚拟机不允许单个程序中的Bitmap占用超过8M的内存,从报错的日志可以看出:7458832-byte大约就是7M多的样子,基本吻合上述数据。在我的项目中大量的使用到了各种图片,因此是因为图片导致内存溢出的的可能性很高。

那么,下面就提供一下解决方案:

第一种方案:

Android堆内存也可自己定义大小 和 优化Dalvik虚拟机的堆内存分配(LZ没试过,不过网上很多人都说可行)。

强制定义自己软件的对内存大小,我们使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例:

private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
//设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理

第二种方案:

手动的回收内存。

示例代码如下:bit为Bitmap对象

if (bit != null && !bit.isRecycled()) {
                    bit.recycle();
                    bit = null;
                }System.gc();

bitmap.recycle()方法用于回收该bitmap所占用的内存,用System.gc()调用一下系统的垃圾回收器。

需要注意的是:回收内存要及时,比如说SurfaceView,就应该在onSurfaceDestroyed这个方法中回收。如果Activity使用了bitmap,就可以在onStop或者onDestroy方法中回收等等。

我首先就是用的这种方法,修改后发现bug出现的频率减小了,但仍然存在。

第三种方案:

既然是图的问题,那就从图片下手。就是使图片体积大小变小。

这也分为两个方面:

1、分辨率不变,图片大小减小2、分辨率改变,图片减小。(用PS都很容易的)

需要注意的是:不要减小得太小而影响了人眼看上去的美感。

以上三种方案,后两种较简单且常用。

另外,因为是Android的图片导致的内存问题,那么就总结了一下与图片相关的方法的性能,结果很有收获啊……(不看不知道,一看吓一跳)

测试的环境为:笔记本i3处理器,64位win7系统,测试手机为小米2S,测试图片大小为500KB

比较Drawable与Bitmap占用内存大小

比较BitmapFactory类的decodeResource方法与decodeStream方法的效率

以及优化后的BitmapFactory类的decodeResource方法。

下面贴上代码与运行图:(每次请只运行一个方法,隐藏另外的三种方法)

public class MainActivity extends Activity {
    int number = 1000;
    Drawable[] array;
    Bitmap bitmap[];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
         testDrawable();
        // testBitmap_decodeResource();
        // testBitmap_decodeStream();
        //testnewBitmap_decodeResource();

    }
    /**
     * 优化后的BitmapFactory类的decodeResource方法
     */
    private void testnewBitmap_decodeResource() {
        bitmap = new Bitmap[number];
        for (int i = 0; i < number; i++) {
            Log.i("", "测试第" + (i + 1) + "张图片");
            //压缩,用于节省BITMAP内存空间--解决BUG的关键步骤
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inSampleSize = 2;//这个的值压缩的倍数(2的整数倍),数值越小,压缩率越小,图片越清晰
            //返回原图解码之后的bitmap对象
            bitmap[i] = BitmapFactory.decodeResource(getResources(),
                    R.drawable.begin_background, opts);
        }

    }
    /**
     * BitmapFactory类的decodeStream方法
     */
    private void testBitmap_decodeStream() {
        bitmap = new Bitmap[number];

        for (int i = 0; i < number; i++) {
            Log.i("", "测试第" + (i + 1) + "张图片");
            bitmap[i] = BitmapFactory.decodeStream(getResources()
                    .openRawResource(R.drawable.begin_background));// 这里换了方法
        }
    }
    /**
     * BitmapFactory类的decodeResource方法
     */
    private void testBitmap_decodeResource() {
        bitmap = new Bitmap[number];

        for (int i = 0; i < number; i++) {
            Log.d("", "测试第" + (i + 1) + "张图片");
            bitmap[i] = BitmapFactory.decodeResource(getResources(),
                    R.drawable.begin_background);
        }

    }
    /**
     * Drawable的使用
     */
    private void testDrawable() {
        array = new BitmapDrawable[number];

        for (int i = 0; i < number; i++) {
            Log.w("", "测试第" + (i + 1) + "张图片");
            array[i] = getResources().getDrawable(R.drawable.begin_background);
        }

    }

}

首先贴出   Drawable的使用   的运行结果:(顺利测试完1000张图片)

BitmapFactory类的decodeResource方法运行结果:(居然只有11张)

运行优化后的BitmapFactory类的decodeResource方法:(优化后可达到46张,且opts.inSampleSize = n;N的参数设置得越大可达到的数量越多,但损失了图片质量)

BitmapFactory类的decodeStream方法:(可达22张图片)

这下,相信大家对Android中与图片相关的这几种方法的性能有直观的认识了吧。其实,在测试时除了看到数量外,还可以看到运行时间上的差距。

Android 内存溢出管理与测试

时间: 2024-10-21 02:11:45

Android 内存溢出管理与测试的相关文章

【Android】Android内存溢出问题---用自行开辟的空间进行对内存管理

public static Bitmap readBitmap(String path) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; options.inPurgeable = true; options.inInputShareable = true; options.inSampleSize = compute

【转载】Android 内存溢出如何发生的。

且谈Android内存溢出 前言 关于android的内存溢出在创新文档库中也有不少,网络上也有很多这方面的资料.所以这遍文章不算是正真意义上的创新,仅仅只是对xxx源码中出现的一些android开发中容易犯错的代码习惯一次总结. 1.  Android的内存溢出是如何发生的 Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的机器为24M.因此我们所能利用的内存空间是有限的.如果我们的内存占用超过了一定的水平就会出现OutOfMemory的错误. 原因主要有两个:

android 内存溢出的一些想法

对于android内存溢出这个问题,小编很是头痛!在这里说下小编自己的想法! 首先内存引用分为强引用,弱引用,软引用,虚引用! 强引用是一个实例引用,根据java的gc原理,如果存在引用,就无法自动回收,所以强引用必须在用完后使其=null ex:Object object = new Object(); object = null; 软引用是在强引用的基础上引用,使用Softreference进行引用,它是除非系统内存不足时才会回收,其它时候均不会回收,适合做cache: ex: Object

android 内存溢出问题分析

最近的项目中,内存一直再增长,但是不知道是什么问题,导致内存溢出,在网上看到了这么一篇关于内存分析与管理的文章,解决了部分问题,感觉这篇文 章还不错,就转帖到我的blog上了,希望对大家有所帮助.如果哪里有不好的地方,给留下言,然后我们大家继续完善内存泄露的问题,对大家都会有所帮助 的,呵呵 一.概述 1 二.Android(Java)中常见的容易引起内存泄漏的不良代码 1 (一) 查询数据库没有关闭游标 2 (二) 构造Adapter时,没有使用缓存的 convertView 3 (三) Bi

android内存溢出问题

最近的项目中,内存一直再增长,但是不知道是什么问题,导致内存溢出,在网上看到了这么一篇关于内存分析与管理的文章,解决了部分问题,感觉这篇文章还不错,就转帖到我的blog上了,希望对大家有所帮助.如果哪里有不好的地方,给留下言,然后我们大家继续完善内存泄露的问题,对大家都会有所帮助的,呵呵 一.概述 1 二.Android(Java)中常见的容易引起内存泄漏的不良代码 1 (一) 查询数据库没有关闭游标 2 (二) 构造Adapter时,没有使用缓存的 convertView 3 (三) Bitm

Android 内存溢出解决方案(OOM)

众所周知,每个Android应用程序在运行时都有一定的内存限制,限制大小一般为16MB或24MB(视平台而定).因此在开发应用时需要特别关注自身的内存使用量,而一般最耗内存量的资源,一般是图片.音频文件.视频文件等多媒体资源:由于Android系统对音频.视频等资源做了边解析便播放的处理,使用时并不会把整个文件加载到内存中,一般不会出现内存溢出(以下简称OOM)的错误,因此它们的内存消耗问题暂不在本文的讨论范围.本文重点讨论的是图片的内存消耗问题,如果你要开发的是一款图片浏览器应用,例如像And

各路搜集,分析Android内存溢出

叙述不当之处,欢迎指正. Android主要应用在嵌入式设备当中,而嵌入式设备由于一些众所周知的条件限制,通常都不会有很高的配置,特别是内存是比较有限的.如果我们编写的代 码当中有太多的对内存使用不当的地方,难免会使得我们的设备运行缓慢,甚至是死机.为了能够使得Android应用程序安全且快速的运行,Android 的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的.一方面,如果程序在运行过程中出现

Android 内存溢出解决方案(OOM) 整理总结

标签:Android加载大 Android 移动开发 在最近做的工程中发现加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,但自己感觉有点乱,特此,今天在不同型号的三款安卓手机上做了测试,因为有效果也有结果,今天小马就做个详细的总结,以供朋友们共同交流学习,也供自己以后在解决OOM问题上有所提高,提前讲下,片幅有点长,涉及的东西太多,大家耐心看,肯定有收获的,里面的很多东西小马也是学习参考网络资料使用的,先来简单讲下下: 一般我们大家在遇到内存问题的时候常用的方式网上也有

Android 内存溢出(Out Of Memory)的总结

内存溢出主要由以下几种情况引起: 1.数据库的cursor没有关闭. 2.构造adapter没有使用缓存contentview. 3.调用registerReceiver后未调用unregisterReceiver(). 4.未关闭InputStream/OutputStream. 5.Bitmap使用后未调用recycle(). 6.Context泄漏. 前5种情况容易发现和解决,只要把该关的及时关闭,该调用的方法及时调用,就不会有太多问题,另外java里还有软引用帮助管理内存: SoftRe