内存优化系列之一

         在进行android开发时,你是否遇到过Out of Memenry (简称OOM,内存溢出)的报错信息?相信很多人都遇到过,特别在是做大量的图片显示时,更是出现得频繁,究其原因,都是在开发时没有注意内存的优化而引起的错误。本系列将重点讲解下关于内存优化相关的技巧,这一章先讲解下内存等相关的基础知识点吧。

 一.  android 回收机制

        GC(Garbage Collector)即垃圾回收站,用于回收在后台的进程或者当前进程的堆,GC的线程优先级是最低的,垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。而android系统每当启动一个应用程序,android系统都会为这个应用分配一个dalivk虚拟机,以便这个应用运行在这个独立的虚拟机上,可是一个虚拟机内存大小一般也是限制的(20M左右),所以一个应用的运行所申请的内存不可能无限大的,当某个应用程序达到该应用虚拟机的内存大小,并且回收不了堆内存,此时将产生OOM报错。因此垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能,其触发条件主要有以下两个:

1.应用的堆内存没有不足的情况下,当应用程序空闲时,即没有应用线程在运行时,GC会被调用。因为GC在优先级最低的线程中进行,所以当应用忙时,GC线程就不会被调用,当应用程序越大时,退到后台时被回收的概率越大。

2.Java堆内存不足时,GC线程会运行。当应用进程在运行过程中new新的对象时,若内存空间不足,JVM就会强制地调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法回收内存,JVM则报“out of memory”的错误,android 应用程序将停止运行。看到这里你肯定会有疑问,不同产家的手机或者同个产家的不同android版本的手机,它的内存是否是一致的呢?是否是网上常说的20M呢?接着将介绍下如果设置android进程的堆内存大小。

二. 堆内存大小的设置

         android 系统可在/system/build.prop文件中配置dalvik堆的相关设定。

先看下该文件跟堆大小设置有关的主要属性:

dalvik.vm.heapstartsize=5m

dalvik.vm.heapgrowthlimit=48m

dalvik.vm.heapsize=128m

(1)dalvik.vm.heapstartsize:堆分配的初始大小,调整这个值会影响到应用的流畅性和整体ram消耗。这个值越小,系统ram消耗越慢,应用程序响应和界面显示就会比较慢,相反,这个值越大系统ram消耗越快,程序更流畅,一些较大的应用经常需要扩张这个堆,从而引发gc和堆调整的策略,会让应用程序反应更快些,这也是内存优化的一种方式。

进程的最大堆内存大小分为大堆和小堆两种,通过在manifes.xml中指定android:largeHeap为true,这样dvm heap最大可达dalvik.vm.heapsize,否则为dalvik.vm.heapgrowthlimit。

(2)dalvik.vm.heapgrowthlimit:当应用程序设置了小堆,那么该应用的极限堆(仅仅针对dalvik堆)为heapgrowthlimit,正常情况下dvm heap的大小是不会超过dalvik.vm.heapgrowthlimit的值,但是程序在运行过程中如果没有合理的回收堆内存,那么dvm heap是会不停的增长,最后运行的应用程序的dvm heap size将超过该dalvik.vm.heapgrowthlimit值,则将引发oom(out of memory)。

(3)dalvik.vm.heapsize:在android应用程序开发过程中android:largeHeap设置为true,dalvik.vm.heapsize就是堆的最大值。既该应用程序在运行过程中可以使用的堆内存上限为dalvik.vm.heapsize,当堆内存没有得到合理的回收等情况下时,一旦该应用程序的dalvik heap size超过这个值,则将直接引发oom错误。

        至于怎么监听应用程序的堆内存大小变化和堆内存优化等问题,将下以后的章节中详细讲解,这一章重点普及下基础知识点,接着继续介绍垃圾回收机制息息相关的基础概念:java的对象引用。

三. java对象引用

1.强引用
       以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。

2.软引用(SoftReference)

        如果一个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

3.弱引用(WeakReference)

       弱引用是一种更容易被GC线程回收的引用,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,当GC线程检测到它的存在,就会立刻回收它的内

4.虚引用

         这里简单介绍下,“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,也就是说虚引用是最容易被回收的。

   这四种引用从最容易被回收开始排序:虚引用、弱引用和空引用、软引用。

 

四. android 垃圾回收跟各对象引用的关系

        当android系统触发了上面讲的两个GC触发条件时,GC线程会开始检查该应用进程的强引用对象是否被引用,如果强引用对象没被引用,那么GC回收该对象;检测是否存在弱引用对象,若存在不管内存是否足够,都回收该弱对象内存,此时还没达到"out of memory "的程序,则不会回收该应用的软引用;但是如果内存不足时,没有垃圾对象(没被引用的对象)可以被回收,也没有弱引用或者虚引用被回收,同时也达到"out of memory"的程度,那么GC会开始检查该应用进程是否存在软引用,如存在立马回收该软引用,避免OOM的错误,如果此时已经没有软引用可以回收了,那么抱歉,你的app将产生Out of Memory的错误。这也意味着你的app需要进行内存优化,内存优化也是本系列技术博客要讲解的重点。待续。。。。。。

你可能感兴趣的:(内存优化系列之一)