Android 内存优化

Android 内存优化
1 静态变量引起内存泄漏
静态变量的生命周期是从这个类被声明开始的,到这个类被垃圾回收器回收才会被销毁,所以,一般情况下,静态变量从所在的类被使用开始就要一直占用着内存空间,知道这个类结束.如果不注意,静态变量会占用大量内存的资源,造成垃圾回收器无法堆内存进行回收,造成内存浪费,
示例 1 定义一个Activity
Private static Resources mResources;
void onCrrate(Bundle state){
Super.onCreate(state);
mResources = this.getResources();
}
这段代码中,静态的mResoutces对象 拥有了当前activity对象的引用,activity又引用了整个页面中所有的对象,例如当横竖屏切换时,activity会重新创建,就会导致第一次创建的activity不能被垃圾回收器回收,导致内存的浪费
2 使用Application 的Context
在Android 中,Application Context 的生命周期和应用的生命周期一样长,如果想保持一个长期生命的对象,并且需要一个context,就可以使用Application对象,可以通过调用Context.getApplicationContext(),或Activity.getApplicaiton() 获取Applciation对象
上面示例 1的代码可以修改成下面这样
mResources = this.getApplcation().getResoutces(); 绕过activity
3 及时关闭资源
Cursor bitmap 等进行释放
4 对Adapter 进行优化
listview的adapter 中 getView 需要复用机制,
Recyclerview 中通过viewholder 进行了复用
4.1 Handler临时性内存泄漏
1 使用一个静态Handler内部类,然后对handler持有的对象使用弱引用,这样回收时,也可以回收Handler持有的对象
2 在activity的Destroy或这Stop时,应该移除消息队列中的消息,避免Looper线程的消息队列中有待处理的消息需要处理
4.2 注册的对象未注销
例如BraodcasReceiver EventBus 未注销造成的内存泄漏 ,我们应该在Activity销毁时及时注销
5 代码 “微优化”
1 创建新的对象都需要额外的内存空间,尽量减少创建新的对象
2 将类 ,变量,方法,等等的可见性修改为最小(public private)
3 针对字符串的拼接,使用StringBuffer 代替String
4 不要在循环当中申明临时变量,不要在循环中捕获异常
5 如果对线程安全没有要求,尽量使用线程不安全的集合对象
6 使用集合对象,如果事先知道其大小,则可以在构造方法中设置初始大小
7 文件读取操作需要使用缓存类,及时关闭文件
8 慎用异常(try catch),使用异常会导致性能降低
9 如果程序会频繁创建线程,则可以考虑使用线程池
6 使用软引用和弱引用
Java 从 JDK1.2版本开始 ,把对象的引用分为四种级别,由高到低依次为:强引用,软引用,弱引用和虚引用
软引用,当内存不足时回收
弱引用,gc时回收
虚引用, 随时可能回收
ReferenceQueue
在于Reference 对象所引用的对象被GC回收时,该Reference对象将会被加入引用队列中(ReferenceQueue)的队列末尾
7 对象的生命周期
1 创建onCreate (为对象分配内村空间,构建对象),
2 应用 In use (此时,对象最少被一个强引用持有)
3 不可见 invisible (当我们的对象,程序不再持有强应用了,如果这个时候被GC扫描到了后,程序就开始判断对象的可达性分析)
4 不可达 Unreachable(程序判断不可达了就会进入下一个阶段)
5 收集 Collected()
6 终结 Finalized (对象被垃圾回收机回收了)
7 对象空间重新分配 Deallocated
8 对象的组成
对象由对象头,实例数据,对齐填充(非必须组成)
对象头由储存对象自身的运行时数据(很多标识性数据),指针类型,若为数组,还应有数组长度的数据
标识性数据包括,(哈希吗,GC分代年龄,锁状态标识,线程只有的锁,偏向线程ID , 偏向时间戳)
Android 内存回收机制
1对象最开始创建出来之后会在Eden区
2 执行gc后,如果对象任然存活,则复制到S0区,
3 当S0 区满时,该区存活对象将复制到S1区,然后清空S0,接下来S1和S0角色互换.
4 当第3步到达一定次数后,存活对象将被复制到Old Generation区
5 当这个对象在Old Generation 区停留一段时间后,在移动到Permanent Generaion 区
堆区的分布情况
Young Generaion 和 old Generation 分为年轻代和老年代
年轻代又分为三个区 eden 区和 survivor 区 和 viutial区
比例为1 : 8 : 1
Survivor 每次转换分代年龄+1 ,加到15之后会进入老年代
年轻代用的GC算法是mimor GC 回收速度快一些
老年代用的GC算法是 full GC 回收速度慢一点
Android 中的内存分区
Dalvik:
Linear Alloc 匿名共享内存
Zygote Space : 存的Zygote 的相关的
Alloc Space: 每个进程独占的
ART:
Non Moving Space
Zygote Space
Alloc Space
Image Space 预加载的类信息
Large Obj Space : 分配大对象 bitmap
可达性分析,重gc root 开始判断,
例如有 静态变量,线程变量,常亮池,JNI指针
垃圾回收算法
1 标记清除算法,
特点 ,位置不连续,产生碎片,效率略低,两边扫描
标记清楚算法会扫描两次,第一次扫描会把哪些对象是可以回收的,哪些对象是正常被引用的标记出来,然后第二次扫描的时候把可以回收的全部回收到,
多次进行内存清除后 内存会千疮百孔,会产生大量的内存碎片,切效率相对比较低
2 复制算法
特点,实现简单,运行效率高,没有内存碎片,利用率只有一半
他会把内存分成两半,当一半块用完的时候,他会进行扫描,把存活的对象移动到另外一边去,剩下这一半的空间全部清除,速度快但利用略只有一半,
3 标记整理算法
特点,没有内存碎片,效率偏低,两边扫描,指针需要调整
内存回收时,第一遍先把存活对象, 未使用对象,可回收对象区别出来,然后第二遍扫描时,进行整理,吧存活的对象顺序放在一边,删除可回收对象,剩下的就是未使用的对象.两遍扫描,效率偏低
4 分代收集算法
综合应用了,复制算法,标记整理算法
Android 独有的
app内存的组成,
Android 给每一个APP分配一个VM.让App运行在dalvik 上,这样即使APP奔溃也不会影响到系统,系统给VM分配了一个内存大小,App可以申请使用的内存大小不能超过硬性逻辑限制,就算物理内存富裕,如果应用超过VM最大内存,就会出现内存溢出crash
由于程序操作的内存空间在heap上,分为java heapsize 和 native heapsize ,- java申请的内存在 VM heap上,所以java申请的内存大小超过VM的逻辑存在限制就会出现内存溢出的问题
Native 层内存申请不受其限制,native层受native process 对内存大小的限制,
App 内存大小 : 每个手机都会对手机内app的内存大小进行修改
修改手机内app内存大小可以在两个地方修改(做 手机系统的程序可以修改,做应用app的没办法修改)
1 startVM 处修改
2 虚拟机内部参数修改
activityManager 可以获取到手机内存
Andoird 低内存杀进程机制
Foreground Processes 前台进程
Visible Processes 可见进程
Service Processes 服务进程
Background Processes 后台进程
Empty Processes 空进程

AMS oom_adj 机制
App - home键 ,app不会被系统杀掉,会改变进程的级别
oom_adj [-16 ,15] 系统把所有的服务分为三十多级,数字越小,越不容易删除
Ams - oom_score_adj [ - 1000 , 1000]
oom_score 得分越高越容易被杀掉
App 前台可见 得分为0
cat /proc/pid/oom_adj

内存三大问题 ,
内存抖动,内存泄漏,内存溢出
OOM问题
1 Java 堆内存溢出
2 无足够联系内存空间
3 FD数量超出限制 (文件句柄)
4 线程数量超出限制
5 虚拟内存不足

常见分析内存命令
MAT
Incoming 被谁持有
Outgoing 持有谁
Shallow Heap 浅堆
Retained Heap 深堆 统计结果

内存优化,总体思想
1 设备分级
2 Bitmap优化
统一图片库
线上 线下监控 hook
3 leakcanary 等借助工具查看

leakcanary
1 找出有泄漏嫌疑的对象 ,原理
2 确证 haha利用这个可达性分析

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值