精华内容
下载资源
问答
  • 前言在日常的Android开发中,每个开发者或多或少都会遇到过OutOfMemoryError这样崩溃信息。如果工程稍微大一些,在monkey测试的崩溃日志也是比较常见的一种。如下是比较常见的一些报错信息:Android:java.lang....

    前言

    在日常的Android开发中,每个开发者或多或少都会遇到过OutOfMemoryError这样崩溃信息。如果工程稍微大一些,在monkey测试的崩溃日志也是比较常见的一种。如下是比较常见的一些报错信息:

    Android:java.lang.OutOfMemoryError: Failed to allocate a 1340012 byte allocation with 72503 free bytes and 70KB until OOM

    OutOfMemoryError: (Heap Size=49187KB, Allocated=41957KB)

    COMPILETODALVIK : UNEXPECTED TOP-LEVEL error :

    java.lang.OutOfMemoryError: Java heap space

    ...

    java.lang.StackOverflowError

    ...

    相对于StackOverflowError而言OutOfMemoryError则是比较常见的一种内存异常。在《深入理解Java虚拟机》一书中有对这两种异常信息的简单描述。

    如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出StackOverflowError;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可以动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError。

    StackOverflowError不常见,主要在渲染复杂布局或者动态缓存数据到数据库时比较常见。而OutOfMemoryError只要内存泄漏多了就有可能导致内存溢出。

    内存泄漏与内存溢出

    内存泄漏 Memeory Leak程序在向系统申请分配内存空间后(new),在使用完毕后未释放。结果导致一直占据该内存单元,我们和程序都无法再使用该内存单元,直到程序结束,这是内存泄露。

    内存溢出 Out Of Memory是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如内存只能分配一个int类型,我却要塞给他一个long类型,系统就出现oom。又比如一车最多能坐5个人,你却非要塞下10个,车就挤爆了。

    内存泄漏的堆积最终会导致内存溢出。从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。

    为什么会产生内存泄漏

    为了判断Java中是否有内存泄漏,首先我们必须了解Java是如何管理内存的。Java的内存管理可以简单理解为对象的分配和释放。在Java中内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)自动完成的。程序员不需要自己调用方法释放内存,但它只能回收无用且不被其它对象引用的那些对象占用的空间。

    Java内存回收机制就是从程序的GC root(静态对象以及堆内存对象等)开始检查引用链,当遍历一遍之后得到上述无法回收的对象以及它们所引用的对象链,组成无法回收的对象集合,而其它孤立的对象就作为垃圾回收。GC为了能够正确释放对象,必须监控每一个对象的状态,包括对象的申请、引用、被引用、赋值等,GC都需要对其进行监控。监控对象的状态是为了更加准确地、及时地释放对象,而释放对象的基本原则就是该对象不再被使用。

    在Java中上述的那些无用的对象由GC负责回收,因此程序员不需要考虑这部分内存泄漏。虽然我们有几个方法可以方位GC,例如System.gc(),但是根据Java语言规范的定义,该方法并不会保证Java的垃圾收集器一定会执行。因为不同的JVM实现者可能使用的是不同的算法实现的GC。通常GC线程的优先级比较低。JVM调用GC的策略也有许多中,有的是当内存使用的一定限度时才会执行GC,也有定时执行的。再者Java编程规范也不建议开发人员自己手动调用System.gc()。

    Android应用程序采用Java编程语言编写,根据上面描述,Java区别于其他语言的一个重要优点就是它通过GC 自动管理内存的回收,Android程序员只需通过内存分配操作创建对象,而无须关心对象占用的空间是如何被收回的。因此很多程序员认为在Java中不必担心内存泄漏的问题,然而实际并非如此,Java中仍然存在着内存泄漏。Android应用程序一般都是运行在移动设备中的,而移动设备中内存的总量非常有限,因此如何合理地规避“内存泄露”问题也就显得十分关键。

    Android中内存介绍

    在Android中获取系统分配内存的大小一般采用如下两种方式:

    ActivityManager mgr= (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

    int memSize=mgr.getMemoryClass();

    int maxSize=mgr.getLargeMemoryClass();

    builder.append("系统分配内存大小:"+memSize+"M\n");

    builder.append("系统分配最大内存:"+maxSize+"M\n\n");

    long totalMem=Runtime.getRuntime().totalMemory()/SIZE_UNIT;

    long freeMem=Runtime.getRuntime().freeMemory()/SIZE_UNIT;

    long maxMem=Runtime.getRuntime().maxMemory()/SIZE_UNIT;

    builder.append("总内存:"+totalMem+"M\n");

    builder.append("剩余内存:"+freeMem+"M\n");

    builder.append("最大内存:"+maxMem+"M\n");

    点击进去可查看到getMemoryClass()和getLargeMemoryClass()源码,实际上它们读取的是配置文件中的数值,文件目录位于/system/build.prop。

    static public int staticGetMemoryClass() {

    // Really brain dead right now -- just take this from the configured

    // vm heap size, and assume it is in megabytes and thus ends with "m".

    String vmHeapSize = SystemProperties.get("dalvik.vm.heapgrowthlimit", "");

    if (vmHeapSize != null && !"".equals(vmHeapSize)) {

    return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));

    }

    return staticGetLargeMemoryClass();

    }

    通过adb命令cat /system/build.prop | grep heap,我们可以查看dalvik内存的配置信息,如下是两个手机中的配置信息:

    dalvik.vm.heapstartsize=8m

    dalvik.vm.heapgrowthlimit=256m

    dalvik.vm.heapsize=512m

    dalvik.vm.heaptargetutilization=0.75

    dalvik.vm.heapminfree=512k

    dalvik.vm.heapmaxfree=8m

    dalvik.vm.heapstartsize=8m

    dalvik.vm.heapgrowthlimit=96m

    dalvik.vm.heapsize=256m

    dalvik.vm.heaptargetutilization=0.75

    dalvik.vm.heapminfree=512k

    dalvik.vm.heapmaxfree=8m

    getMemoryClass()获取到的是dalvik.vm.heapgrowthlimit的大小,而getLargeMemoryClass()获取到的就是dalvik.vm.heapsize配置项的大小。

    dalvik.vm.heapstartsize相当于虚拟机的-Xms配置,该项用来设置堆内存的初始大小。

    dalvik.vm.heapgrowthlimit相当于虚拟机的 -XX:HeapGrowthLimit配置,该项用来设置一个标准的应用的最大堆内存大小。一个标准的应用就是没有使用android:largeHeap的应用。

    dalvik.vm.heapsize相当于虚拟机的-Xmx配置,该项设置了使用android:largeHeap的应用的最大堆内存大小。

    dalvik.vm.heaptargetutilization相当于虚拟机的 -XX:HeapTargetUtilization,该项用来设置当前理想的堆内存利用率。其取值位于0与1之间。当GC进行完垃圾回收之后,Dalvik的堆内存会进行相应的调整,通常结果是当前存活的对象的大小与堆内存大小做除法,得到的值为这个选项的设置,即这里的0.75。注意,这只是一个参考值,Dalvik虚拟机也可以忽略此设置。

    dalvik.vm.heapminfree对应的是-XX:HeapMinFree配置,用来设置单次堆内存调整的最小值。

    dalvik.vm.heapmaxfree对应的是-XX:HeapMaxFree配置,用来设置单次堆内存调整的最大值。通常情况下,还需要结合上面的 -XX:HeapTargetUtilization的值,才能确定内存调整时,需要调整的大小。

    一般情况下Runtime.getRuntime().maxMemory()获取到的最大内存大小跟getMemoryClass()大小相同,但是如果在清单文件AndroidManifest.xml中设置了android:largeHeap="true",这时候获取到的值可能就是getLargeMemoryClass()大小,这里也是一般而言,因为有部分手机中设置了android:largeHeap="true"也无效。还有一点需要注意,使用ActivityManager的getMemoryClass()或者getLargeMemoryClass()获取到的内存值的单位是M,但是Runtime.getRuntime()获取到的是bit。

    查看整体内存分配

    我们可以使用下面的 adb 命令观察应用内存在不同类型的 RAM 分配之间的划分情况:

    adb shell dumpsys meminfo [-d]

    -d 标志会打印与 Dalvik 和 ART 内存使用情况相关的更多信息。输出列出了应用的所有当前分配,单位为千字节。

    如下是一个简单的demo的dumpsys:

    Applications Memory Usage (in Kilobytes):

    Uptime: 544929 Realtime: 544929

    ** MEMINFO in pid 1712 [com.sunny.memory] **

    Pss Private Private SwapPss Heap Heap Heap

    Total Dirty Clean Dirty Size Alloc Free

    ------ ------ ------ ------ ------ ------ ------

    Native Heap 3490 3280 0 0 14336 12849 1486

    Dalvik Heap 826 800 0 0 2213 677 1536

    Dalvik Other 696 696 0 0

    Stack 72 72 0 0

    Ashmem 6 0 0 0

    Other dev 10 0 8 0

    .so mmap 1625 160 20 0

    .apk mmap 3032 2316 12 0

    .ttf mmap 96 0 0 0

    .dex mmap 1794 4 144 0

    .oat mmap 457 0 0 0

    .art mmap 3876 3680 0 0

    Other mmap 2334 4 1736 0

    Unknown 458 436 0 0

    TOTAL 18772 11448 1920 0 16549 13526 3022

    App Summary

    Pss(KB)

    ------

    Java Heap: 4480

    Native Heap: 3280

    Code: 2656

    Stack: 72

    Graphics: 0

    Private Other: 2880

    System: 5404

    TOTAL: 18772 TOTAL SWAP PSS: 0

    Objects

    Views: 17 ViewRootImpl: 1

    AppContexts: 3 Activities: 1

    Assets: 13 AssetManagers: 3

    Local Binders: 10 Proxy Binders: 17

    Parcel memory: 2 Parcel count: 10

    Death Recipients: 0 OpenSSL Sockets: 0

    WebViews: 0

    SQL

    MEMORY_USED: 0

    PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0

    VSS – Virtual Set Size虚拟耗用内存(包含共享库占用的内存)。

    RSS – Resident Set Size实际使用物理内存(包含共享库占用的内存)。

    PSS – Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)。

    USS – Unique Set Size进程独自占用的物理内存(不包含共享库占用的内存)。

    USS是针对某个进程开始有可疑内存泄露的情况,是一个程序启动了会产生的虚拟内存,一旦这个程序进程杀掉就会释放!不过USS需要通过root的手机。一般没有root的手机我们可以获取PSS。一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS

    有关不同内存的详细信息,这里重点列出ViewRootImpl、AppContexts和Activities。

    ViewRootImpl当前活动应用的根视图数量。每个根视图都与一个窗口关联,因此有助于您确定涉及对话框或其他窗口的内存泄漏。

    AppContexts 和 Activities当前活动的应用 Context 和 Activity 对象数量。这可以帮助您快速确定由于存在静态引用(比较常见)而无法进行垃圾回收的已泄漏 Activity 对象。这些对象经常拥有很多关联的其他分配,因此成为跟踪大型内存泄漏的一种不错的方式。

    有关内存整体分配的更多内容可以参看调查 RAM 使用情况。

    小结

    本篇主要介绍有关内存溢出的一些概念,以及在Android中如何查看相关内存信息。后续再继续介绍有关内存溢出的几种常见现象,并介绍如何根据不同现象的内存泄漏做出进一步的解决方式。最后会介绍在开发中一旦发生了内存泄漏,该如何使用工具进行探测分析内存溢出。

    展开全文
  • 今天发现正在做的项目,时不时的会报错:dalvikvm heap out of memory on a 7458832-byte allocation (堆分配的内存溢出)为什么会内存溢出呢?我以前从未遇见这种情况。后来在网上查了查资料,还是挺多的。怎么说呢...

    今天发现正在做的项目,时不时的会报错: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 extendsActivity {int number = 1000;

    Drawable[] array;

    Bitmap bitmap[];

    @Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    testDrawable();//testBitmap_decodeResource();//testBitmap_decodeStream();//testnewBitmap_decodeResource();

    }/*** 优化后的BitmapFactory类的decodeResource方法*/

    private voidtestnewBitmap_decodeResource() {

    bitmap= newBitmap[number];for (int i = 0; i < number; i++) {

    Log.i("", "测试第" + (i + 1) + "张图片");//压缩,用于节省BITMAP内存空间--解决BUG的关键步骤

    BitmapFactory.Options opts = newBitmapFactory.Options();

    opts.inSampleSize= 2;//这个的值压缩的倍数(2的整数倍),数值越小,压缩率越小,图片越清晰//返回原图解码之后的bitmap对象

    bitmap[i] =BitmapFactory.decodeResource(getResources(),

    R.drawable.begin_background, opts);

    }

    }/*** BitmapFactory类的decodeStream方法*/

    private voidtestBitmap_decodeStream() {

    bitmap= newBitmap[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 voidtestBitmap_decodeResource() {

    bitmap= newBitmap[number];for (int i = 0; i < number; i++) {

    Log.d("", "测试第" + (i + 1) + "张图片");

    bitmap[i]=BitmapFactory.decodeResource(getResources(),

    R.drawable.begin_background);

    }

    }/*** Drawable的使用*/

    private voidtestDrawable() {

    array= newBitmapDrawable[number];for (int i = 0; i < number; i++) {

    Log.w("", "测试第" + (i + 1) + "张图片");

    array[i]=getResources().getDrawable(R.drawable.begin_background);

    }

    }

    }

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

    9ea07593a124393f7515c2486840f28a.png

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

    4decf07b96207c5eb9693c07f0c80e27.png

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

    ff45d0024d2043c9e1bb05c00ed3d052.png

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

    37f9dbfcd54bda1501ccc2f32ca39409.png

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

    原文:http://www.cnblogs.com/scetopcsa/p/3866322.html

    展开全文
  • 一、内存泄漏和内存溢出的区别内存溢出 out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出内存溢出通俗...

    一、内存泄漏和内存溢出的区别

    内存溢出 out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存溢出通俗的讲就是内存不够用。(一般是客观存在的)

    内存泄露 memory leak:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。(程序代码漏洞)

    二、内存泄露原因:(总结大概有以下几种)

    1、Handler 引起的内存泄漏。

    解决:将Handler声明为静态内部类,就不会持有外部类Activity的引用,其生命周期就和外部类无关,

    如果Handler里面需要context的话,可以通过弱引用方式引用外部类(非静态内部类拥有对外部类的强引用)

    2、单例模式引起的内存泄漏。

    解决:Context是ApplicationContext,由于ApplicationContext的生命周期是和app一致的,不会导致内存泄漏

    3、非静态内部类创建静态实例引起的内存泄漏。

    解决:把内部类修改为静态的就可以避免内存泄漏了

    4、非静态匿名内部类引起的内存泄漏。

    解决:将匿名内部类设置为静态的。

    5、注册/反注册未成对使用引起的内存泄漏。

    解决:注册广播接受器、EventBus等,记得解绑。

    6、资源对象没有关闭引起的内存泄漏。

    解决:在这些资源不使用的时候,记得调用相应的类似close()、destroy()、recycler()、release()等方法释放。

    7、集合对象没有及时清理引起的内存泄漏。

    解决:通常会把一些对象装入到集合中,当不使用的时候一定要记得及时清理集合,让相关对象不再被引用。

    主要原因:

    主要是由于生命周期不匹配导致的。Android中的组件都是有特定生命周期的,而当这些组件中存在着不可释放的变量时,组件的生命周期便会出现异常,导致无法被GC释放。如生命周期较长的类使用Activity的Context, 导致Activity被引用, 无法被及时回收. 除了需要Activity页面支持的控件类, 如Dialog等, 其他全部使用应用的Context替换Activity的Context, 即Context.getApplicationContext(). 还有就是单例不要持有页面的控件, 单例持有控件, 控件附属页面, 最终页面得不到释放, 单例可以使用回调修改页面, 内部仅仅保留处理数据部分.

    三、内存泄漏产生后如何查找

    LeakCanary是检测App内存泄露的工具, 内存泄露是Android开发中常见的问题, 使用程序的稳定性下降.

    1.先写一个导致内存泄漏的代码

    /**

    * 内存泄漏的

    */

    public class LeakActivity extends AppCompatActivity {

    static Demo sDemo;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_leak);

    if (sDemo == null) {

    sDemo = new Demo();

    }

    finish();

    }

    class Demo {

    }

    }

    分析:通过简单的例子看看它的效果知道,内存泄漏比较容易发生的,就是因为生命周期不匹配导致。

    这个Activity中,存在一个静态的Demo实例,并且这个实例在Activity初始化的时候也进行了初始化,接着我们在初始化完毕后finish掉这个Activity。

    因为sDemo是一个静态的变量并且不为null,所以GC不会将其清理,而Activity因为持有这个静态变量,生命周期也不能正常执行,这样这个Activity就被泄漏了。

    2、集成LeakCanary

    (1).添加依赖:

    apt 'com.jakewharton:butterknife-compiler:8.1.0'

    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'

    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'

    (2).引入代码

    public class MyApplication extends Application {

    @Override

    public void onCreate() {

    super.onCreate();

    //检测内存泄漏的

    LeakCanary.install(this);

    }

    }

    配置非常简单, 会增加一个附属应用, 去掉Application的引用, 就可以移除LeakCanary.

    3.多次点击启动内存泄漏的页面,就会报OOM

    4.运行项目后会多出现一个图标,打开leaks

    521ce32fee3e

    image.png

    521ce32fee3e

    image.png

    LeakCanary的内存泄露提示一般会包含三个部分:

    第一部分(LeakActivity类的sDemo变量)引用

    第二部分(LeakActivity类的sDemo变量), 导致

    第三部分(MainActivity类)泄露.

    应用最常见的泄露位置就是Activity的实例,但LeakCanary会在界面中显示泄漏信息,这样追踪泄漏的地方就不难了。

    展开全文
  • Android 内存溢出和内存泄漏的问题在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?怎么避免?”通过这篇文章,你可以回答出来了。内存溢出(OOM)是指程序在申请内存时,没有足够的内存空间供其...

    Android 内存溢出和内存泄漏的问题

    在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?怎么避免?”通过这篇文章,你可以回答出来了。

    内存溢出(OOM)是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如只申请了一个integer,但给它存了long才能存下的数,那就会出现内存溢出。

    内存泄露(memory leak)是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

    内存泄漏最终会导致内存溢出。

    如何避免内存溢出?

    强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。 当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

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

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

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

    1,释放强引用,使用软引用和弱引用;

    2,图像处理

    大部分的OOM都是发生在图片加载上的,当我们加载大图时,需要特别注意避免OOM的发生。

    处理大图片时,不管你的手机内存有多大,如果不对图片进行处理,都有可能会发生内存溢出问题。

    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的模式也能降低图片占用的内存大小。

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

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

    BitmapFactory.Options options = new BitmapFactory.Options();

    options.inJustDecodeBounds = true; // 不把图片加载到内存中

    Bitmap btimapObject = BitmapFactory.decodeFile(myImage.getAbsolutePath(), options);

    我们不应该把解决OOM的问题寄托在争取最大的内存上,应该通过合理的代码编写来尽可能的规避OOM问题。

    如何避免内存泄漏?

    1,在 onDestroy()方法中显示调用mThread.close();以此来结束该线程,这就避免了线程的内存泄漏问题。

    2,使用application context 代替activity context;

    3,资源对象没关闭造成的内存泄漏,如Cursor没有close掉;

    4,Bitmap记得recycle掉;

    5,构造Adapter时,没有使用缓存的convertView。

    感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

    展开全文
  • Android中的内存泄漏和内存溢出

    千次阅读 2021-12-09 15:45:20
    一、内存溢出和内存泄漏的概念理解 **内存溢出:**是指程序代码片段被执行申请内存时,没有足够的内存空间,导致OOM异常。 OOM:即内存溢出,out of momery。 Android系统为每一个应用程序申请的内存是有限的(为什么...
  • Android 内存溢出和内存泄漏的问题在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?怎么避免?”通过这篇文章,你可以回答出来了。内存溢出(OOM)是指程序在申请内存时,没有足够的内存空间供其...
  • Android内存溢出及内存泄漏原因进行发布时间:2020-08-23 15:18:36来源:脚本之家阅读:111作者:志不坚者智不达内存溢出(Out Of Memory):Android系统中每一个应用程序可以向系统申请一定的内存,当申请的内存不够...
  • 内存溢出的主要导致原因有如下几类:应用代码存在内存泄露,长时间积累无法释放导致OOM;应用的某些逻辑操作疯狂的消耗掉大量内存(譬如加载一张不经过处理的超大超高清图片等)导致超过阈值OOM;可以发现,无论哪种...
  • 第一种方法--及时回收bitmap内存:一般而言,回收bitmap内存可以用到以下代码if(bitmap!=null&&!bitmap.isRecycled()){bitmap.recycle();bitmap=null;}System.gc();bitmap.recycle()方法用于回收该bitmap所...
  • 100) 05-29 18:47:07.228: E/AndroidRuntime(32247): at android.view.View$PerformClick.run(View.java:18698) 05-29 18:47:07.228: E/AndroidRuntime(32247): at android.os.Handler.handleCallback(Handler.java:...
  • 避免内存溢出的方法,主要是对以下三个方面对程序进行优化内存引用在处理内存引用之前,我们先来复习下什么是强引用、软引用、弱引用、虚引用强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收...
  • 一、Android内存机制 Android的程序由Java语言编写,所以Android内存管理与Java的内存管理相似。程序员通过new为对象分配内存,所有对象在java堆内分配空间;然而对象的释放是由垃圾回收器来完成的。C/C++中的...
  • 下面这些都是我在做各个app时总结出来的,希望对各位有用:1.Android内存溢出原因当图片过大,或图片数量较多时使用BitmapFactory解码图片会出java.lang.OutOfMemoryError: bitmap size exceeds VM budget,要想正常...
  • 最近项目马上结束了在对项目进行检查有没有内存泄漏的地方,这里使用的是leakcanary。使用步骤很简单:添加依赖:dependencies { debugCompile '...
  • 方法6:Android内存也可以自己定义大小和优化Dalvik虚拟机的内存 复制内容到剪贴板 代码: private final static int CWJ_HEAP_SIZE= 6*1024*1024; private final static float TARGET_HEAP_UTILIZATION = 0.75f; ...
  • 内存溢出(Out Of Memory):Android系统中每一个应用程序可以向系统申请一定的内存,当申请的内存不够用的时候,就产生了内存溢出。 内存泄漏:当某个对象不再被使用,即不再有变量引用它时,该对象占用的内存就会...
  • Android内存溢出分析

    2021-06-06 04:08:19
    OOM(内存溢出)和Memory Leak(内存泄露)有什么关系?OOM可能是因为Memory Leak,也可能是你的应用本身就比较耗内存(比如图片浏览型的,或者应用本身的设计有问题)。所以,出现OOM不一定是Memory Leak。同样,Memory ...
  • 1:首先,我们来说一下为什么会有OOM(内存溢出)因为安卓系统的APP每个进程或虚拟机有最大内存限制,一旦超过这个限制就会抛出OOM异常,跟手机剩余内存是否充足没有太大关系。2 :很多人会认为内存泄露跟内存溢出没...
  • 第一种方法--及时回收bitmap内存:一般而言,回收bitmap内存可以用到以下代码if(bitmap!=null&&!bitmap.isRecycled()){bitmap.recycle();bitmap=null;}System.gc();bitmap.recycle()方法用于回收该bitmap所...
  • 基础JAVA是在JVM所虚拟出的内存环境中运行的,内存分为三个区:堆、栈和方法区。栈(stack):是简单的数据结构,程序运行时系统自动分配,使用完毕后自动释放。优点:速度快。堆(heap):用于存放由new创建的对象和数...
  • Bitmap对象的处理 不要在主线程中处理图片 使用Bitmap对象... 注销监听器 在onPause()/onDestroy()方法中解除监听器,包括在Android自己的Listener,Location Service或Display Manager Service以及自己写的Listener。
  • /* Shutdown intent */ private final String INTENT_ACTION_REQUEST_SHUTDOWN = "android.intent.action.ACTION_REQUEST_SHUTDOWN"; @Override public void onCreate(Bundle savedInstanceState) { Log.v(TAG, ...
  • OOM(OutOfMemory)内存溢出 OOM指申请的内存没有足够,导致出现OutOfMemory的一种现象、 查看内容限制的方式如下,可以使用adb命令如下图 OOM产生的几大因素 内存泄漏 长期的内存泄漏最终会导致OOM内存...
  • 231) at io.reactivex.Scheduler$Worker.a(Scheduler.java:371)复制代码 由日志可以看出这是由Rxjava2内部,往线程池中添加任务,所报出的栈内存溢出。 本人使用的Rxjava2 (版本是2.2.2);线程调用器使用的Scheduler...
  • android 内存泄漏

    2021-06-04 01:59:03
    相信大部分童靴都有听说个名词:内存泄漏究竟什么是内存泄漏,它具体有什么危害呢?且听我娓娓道来JVM/ART首先为大家普及下,Java 运行时是有一套虚拟机机制存在的:JVM(Java 虚拟机)是一个虚构出来的运行 Java 程序...
  • Android避免内存溢出(Out of Memory)方法总结避免内存溢出的方法,主要是对以下三个方面对程序进行优化武汉Android培训内存引用在处理内存引用之前,我们先来复习下什么是强引用、软引用、弱引用、虚引用强引用:强...
  • 这是因为final boolean switchChecked = silent; 在你的setOnClickListener你在switchChecked传递静默,并且由于这个silent = settings.getBoolean("switchkey", false); ,silent总是为false silent = settings....
  • 我有点困惑这个问题,我知道在堆栈溢出方面有很多问题,但在我的情况下。 什么都没有给出预期的结果。上下文:我使用Android OpenCV和Tesseract,所以我可以阅读护照中的MRZ区域。 当相机启动时,我将输入帧传递给...
  • {@Overrideprotected String doInBackground(String params){if (!animationDrawable.isRunning()){animationDrawable.stop();animationDrawable.start();}return "";}}ImageView image = (ImageView) findViewById...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,907
精华内容 12,762
关键字:

安卓内存溢出

友情链接: tcp connect to aliyun.rar