Android避免内存溢出(Out of Memory)方法汇总

避免内存溢出的方法,主要是对以下三个方面对程序进行优化

内存引用

在处理内存引用之前,我们先来复习下什么是强引用、软引用、弱引用、虚引用
强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。 当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

软引用:如果一个对象只具有软引用,但内存空间足够时,垃圾回收器就不会回收它;直到虚拟机报告内存不够时才会回收, 只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

弱引用:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存。 不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。 弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

虚引用:虚引用可以理解为虚设的引用,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。 虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。 当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。 程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。 如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

1、释放强引用

一般我们在声明对象变量时,使用完后就不管了,认为垃圾回收器会帮助我们回收这些对象所指向的内存空间,实际上如果这个对象的内存空间还处在被引用状态的话,垃圾回收器是永远不会回收它的内存空间的,只有当这个内存空间不被任何对象引用的时候,垃圾回收器才会去回收。
所以我们在使用完对象后,可以把对象置为空,这样我的垃圾回收器gc就会在合适的时候释放掉为该对象分配的内存空间

Object obj = new Object(); obj = null;

当然,在置为空前要确认是否不再需要使用该对象了,如果需要随时使用这个对象,则不能这么做

2、使用软引用

在jvm报告内存不足之前会清除所有的软引用,这样的话gc就可以收集到很多软引用释放出来的内存空间,从而解决内存吃紧的问题,避免内存溢出,什么时候被回收取决于gc的算法和gc运行时可用的内存大小。
我们可以用SoftReference来封装强引用的对象

String str = "zhuwentao"; // 强引用 SoftReference<String> strSoft = new SoftReference<String>(str); // 使用软引用封装强引用

3、使用弱引用
gc收集弱引用对象的执行过程和软引用一样,只是gc不会根据内存情况来决定是否回收弱引用的对象。

String str = "zhuwentao"; // 强引用 WeakReference<String> strWeak = new WeakReference<String>(str); // 使用弱引用封装强强引用

如果你希望能够随时取得某个对象的信息,但又不希望影响该对象的垃圾回收,则应该使用WeakReference来记住该对象,而不是使用一般的Reference。

图像处理

大部分的OOM都是发生在图片加载上的,当我们加载大图时,需要特别注意避免OOM的发生。
处理大图片时,不管你的手机内存有多大,如果不对图片进行处理,都有可能会发生内存溢出问题。
因为Android系统会为每一个应用分配一定大小的内存,并不会把整个系统内存全部分给应用,所以不管你手机内存多大,对每个App来说,它能使用的内存都是有限的。
这和PC端是有很大的不同,PC端如果内存不够了还可以请求使用虚拟内存,而Android系统可没这个机制。

1、在内存中压缩图片

装载大图片时需要对图片进行压缩,使用等比例压缩的方法直接在内存中处理图片

Options options = new BitmapFactory.Options(); options.inSampleSize = 5; // 原图的五分之一,设置为2则为二分之一 BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);

这样做要注意的是,图片质量会变差,inSampleSize设置的值越大,图片质量就越差,不同的手机厂商缩放的比例可能不同。

2、使用完图片后回收图片所占内存

由于Android外层是使用java而底层使用的是c语言在里层为图片对象分配的内存空间。
所以我们的外部虽然看起来释放了,但里层却并不一定完全释放了,我们使用完图片后最好再释放掉里层的内存空间。

if (!bitmapObject.isRecyled()) { // Bitmap对象没有被回收 bitmapObject.recycle(); // 释放 System.gc(); // 提醒系统及时回收 }

3、降低要显示的图片色彩质量

Android中Bitmap有四种图片色彩模式:
ALPHA_8:每个像素需要占用内存中的1byte
RGB_565:每个像素需要占用内存中的2byte
ARGB_4444:每个像素需要占用内存中的2byte
ARGB_8888:每个像素需要占用内存中的4byte
我们创建Bitmap时,默认的色彩模式是ARGB_8888的,这种色彩模式是质量最高的,当然这样的模式占用的内存也最大。
而ARGB_4444每个像素只占用2byte,所以使用ARGB_4444的模式也能降低图片占用的内存大小。

BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_4444; Bitmap btimapObject = BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);

其实大多数图片设置成ARGB_4444模式后,在显示上是看不出与ARGB_8888模式有什么差别的,只是在具有渐变色效果的图片时,可能会让渐变色呈现色彩条样的效果。
这种降低色彩质量的方法对内存的降低效果不如方法1明显。

4、查询图片信息时不把图片加载到内存中

有时候我们取得一张图片,也许只是为了获得这个图片的一些信息,比如图片的width、height等信息,不需要显示到界面上,这个时候我们可以不把图片加载到内存中。

BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 不把图片加载到内存中 Bitmap btimapObject = BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);

inJustDecodeBounds属性,如果值为true,那么将不返回实际的Bitmap对象,也不给其分配内存空间,但允许我们查询图片宽、高、大小等基本信息。
(获取原始宽高:options.outWidth,options.outHeight)

VMRuntime

VMRuntime是Android SDK中提供的一个类。
只在Android2.3以前有用,2.3以后的SDK就不支持了,所以这个VMRuntime并不通用。
这里简单介绍下就好了。

1、优化Dalvik虚拟机的堆内存分配

VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。

private final static float TARGET_HEAP_UTILIZATION = 0.75f; VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);

2、自定义堆内存大小
强制定义Android给当前App分配的内存大小,使用VMRuntime设置应用最小堆内存。

// 设置最小heap内存为 6MB 大小 private final static int HEAP_SIZE = 6 * 1024 * 1024 ; VMRuntime.getRuntime().setMinimumHeapSize(HEAP_SIZE);

largeHeap
让Dalvik虚拟机为App分配更大的内存,该方法能为我们的App争取到更多内存空间,从而缓解内存不足的压力
可以在程序中使用ActivityManager.getMemoryClass()方法来获取App内存正常使用情况下的大小,通过ActivityManager.getLargeMemoryClass()可获得开启largeHeap时最大的内存大小

1、使用方法

该方法使用非常简单,只要在AndroidManifest.xml文件中的<application>节点属性中加上”android:largeHeap="true"“

<application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:largeHeap="true"

2、注意

Dalvik为我们App增加的内存很可能是通过杀死其它后台进程获取的内存,这样的做法对于一个开发者来说并不道义
我们不应该把解决OOM的问题寄托在争取最大的内存上,应该通过合理的代码编写来尽可能的规避OOM问题。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-09-21 16:55:07

Android避免内存溢出(Out of Memory)方法汇总的相关文章

android的BitmapFactory.Options使用及内存溢出OOM的优化方法

android中BitmapFactory.Options的使用是在加载图片时,就从图片的加载和使用说起 怎样获取图片的大小?首先我们把这个图片转成Bitmap,然后再利用Bitmap的getWidth()和getHeight()方法就可以取到图片的宽高了.新问题又来了,在通过BitmapFactory.decodeFile(String path)方法将突破转成Bitmap时,遇到大一些的图片,我们经常会遇到OOM(Out Of Memory)的问题.怎么避免它呢?这就用到了我们上面提到的Bi

Android编程内存溢出与防范方法浅析_Android

本文实例讲述了Android编程内存溢出与防范方法.分享给大家供大家参考,具体如下:  Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M.但是Android采用的是Java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开发的时候,内存的限制问题会给我们带来内存溢出等严重问题.在我们不使用一些内存的时候,我们要尽量在Android或者其他平台上避免在运行其他程序时,保存必要的状态,使得一些死进程所带来的内存问题,应该尽量在关闭程序

Android编程内存溢出与防范方法浅析

本文实例讲述了Android编程内存溢出与防范方法.分享给大家供大家参考,具体如下: Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小一般是16M.但是Android采用的是Java语言编写,所以在很大程度上,Android的内存机制等同于Java的内存机制,在刚开始开发的时候,内存的限制问题会给我们带来内存溢出等严重问题.在我们不使用一些内存的时候,我们要尽量在Android或者其他平台上避免在运行其他程序时,保存必要的状态,使得一些死进程所带来的内存问题,应该尽量在关闭程序或

Android手机内存中文件的读写方法小结

  Android手机内存中文件的读写方法小结         这篇文章主要介绍了Android手机内存中文件的读写方法,实例总结了Android针对文件读写操作的相关技巧,非常具有实用价值,需要的朋友可以参考: 如何对手机内存中的文件数据进行读写呢? Context提供了领个方法来打开该应用程序的数据文件夹中的文件I/O流,具体如下: ? 1 FileInputStream openFileInput(String name) 打开应用程序的数据文件夹下的name文件对应的数据流 ? 1 Fi

紧急求救:android json 内存溢出

问题描述 紧急求救:android json 内存溢出 代码如下: public JSONObject SetDataToJson() { JSONObject LCYDataJSON = new JSONObject(); try { LCYDataJSON.put("MODE", lcydata.mode); LCYDataJSON.put("date", lcydata.date); LCYDataJSON.put("GPSSta", lc

Android遇到内存溢出(Out Of Memory)BUG的经验与解决方法

http://blog.csdn.net/ekechang/article/details/6706602 突然出现的Out Of Memory这个BUG导致我们项目中断了好几天,在经过不断地摸索之后,今天终于得到了解决.鉴于其强大的破坏力与多发性(尤其是当开发图形丰富的软件时),在此将解决方法同大家分享,希望大家以后少走弯路,而本人水平有限,如有不当,还望指教! 那么,首先让我们来看看遇到这个BUG时系统输出的Log: 按我们的经验一行一行地分析,发现了报错的原因:bitmap size ex

Bbitmap 设置图片尺寸,避免 内存溢出 OutOfMemoryError的优化方法

android 中用bitmap 时很容易内存溢出,报如下错误: Java代码   Java.lang.OutOfMemoryError : bitmap size exceeds VM budget      ● 主要是加上这段: Java代码   BitmapFactory.Options options = new BitmapFactory.Options();                    options.inSampleSize = 2;      ● eg1:(通过Uri取

Tomcat内存溢出分析及解决方法_java

JVM管理两种类型的内存,堆和非堆.堆是给开发人员用的上面说的就是,是在JVM启动时创建:非堆是留给JVM自己用的,用来存放类的信息的.它和堆不同,运行期内GC不会释放空间. 一.内存溢出类型 1.java.lang.OutOfMemoryError: PermGen space JVM管理两种类型的内存,堆和非堆.堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的.它和堆不同,运行期内GC不会释放空间.如果web app用了大量的第三方jar或者

java中三种常见内存溢出错误的处理方法(good)

相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深入的认识. 在解决java内存溢出问题之前,需要对jvm(java虚拟机)的内存管理有一定的认识.jvm管理的内存大致包括三种不同类型的内存区域:Permanent Generation space(永久保存区域).Heap space(堆区域).Java Stacks(Java栈).其中永久保存区域主要存放Class