Android内存优化

虚拟机

Android的虚拟机是Dalvik,Dalvik是指令集基于寄存器架构,执行其特有的文件格式——dex字节码,以此来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。
我们所谓的内存优化,其实就是Dalvik内存的优化。
在这里要介绍几个概念:
dalvik heap:用于分配对象,处理图像
Native Heap: malloc分配,受系统限制
Android系统对dalvik的虚拟机heapsize作了硬性限制,当java进程申请的java空间超过阈值时,就会抛出OOM异常(这个阈值可以是48M、24M、16M等,视机型而定),可以通过adb shell getprop | grep dalvik.vm.heapgrowthlimit查看此值。
也就是说,程序发生OMM并不表示RAM不足,而是因为程序申请的java heap对象超过了dalvik 的限制。

如何查看进程的内存信息

使用adb shell dumpsys meminfo + packagename/pid

使用adb shell procrank查看进程内存信息

这里介绍几个概念:
VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

如何突破虚拟机的内存限制

创建子进程

创建一个新的进程,那么我们就可以把一些对象分配到新进程的heap上了,从而达到一个应用程序使用更多的内存的目的,当然,创建子进程会增加系统开销,而且并不是所有应用程序都适合这样做,视需求而定。
创建子进程的方法:使用android:process标签

使用jni在native heap上申请空间

nativeheap的增长并不受dalvik vm heapsize的限制,native heap size已经远远超过了dalvik heap size的限制。
只要RAM有剩余空间,程序员可以一直在native heap上申请空间,当然如果 RAM快耗尽,memory killer会杀进程释放RAM。大家使用一些软件时,有时候会闪退,就可能是软件在native层申请了比较多的内存导致的。

内存优化的方法:

使用优化过的数据容器

如SparseArray,SparseBooleanArray,LongSparseArray,这是android提供的类,翻译一下就是稀疏数组,所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。

尽量避免使用Enum

枚举相对于静态常量来说,需要两倍甚至更多的内存。

频繁修改时使用 StringBuffer(线程安全)或 StringBuilder(线程不安全)

使用String修改字符串时,若修改后字符串在字符串常量区不存在,便会新生成一个String对象。

对于常量,请尽量使用static final

如果使用final定义常量之后,会减少编译器在类生成时初始化<clinit>方法调用时对常量的存储,对于int型常量,将会直接使用其数值来进行替换,而对于String对象将会使用相对廉价的“string constant”指令来替换字段查找表。
但是如果这个变量持有acivity的对象引用,可能会造成内存泄漏。

对象不用时最好显式置为Null

对象不用时最好显式置为Null可以减少GC开销。

对bitmap的处理

对于bitmap的处理可以参考我之前的一篇文章
http://www.jianshu.com/p/213fc03d0665

listview

listview对于内存的优化,无非就是view的复用,和使用viewholder,这个是很基础的东西,这个不做过多介绍。

使用弱引用和软引用

使用弱引用和软引用,一定要注意一件事,对于变量被回收后,可能出现的空指针问题。
所谓软引用,只有当内存空间不足了,才会回收这些对象的内存。这个可以考虑用作高速缓存
所谓弱引用,被垃圾回收器扫描到后即被回收。只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有 弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

UI的相关处理

利用系统资源,不引入额外的资源,比如

(http://androidbackground/) ="@[android:color/transparent]

通用模块抽离

使用<include layout > 可以将背景,头部标题栏,底部导航,ListView进行抽离。

ViewStub

ViewStub是一个隐藏的,不占用内存空间的视图对象,它可以在运行时延迟加载布局资源文件。
*更多的开发知识,可以关注我的公众号:

《Android内存优化》

    原文作者:mymdeep
    原文地址: https://www.jianshu.com/p/adff000ee347
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞