Android性能优化学习记录(二)稳定性与内存优化
Android性能优化学习记录(二)稳定性
这里写目录标题
- Android性能优化学习记录(二)稳定性
- 一、稳定性
- ApplicationNotResponding
- Crash
- 稳定性总结
- 二、内存优化
- 作用
- 1. 储备知识:Android 内存管理机制
- 1.1 简介
- 1.2 针对进程的内存策略
- 1.3 针对对象、变量的内存策略
- a. 内存分配策略
- b. 内存释放策略
- 2. 常见的内存问题 & 优化方案
- 2.1 内存泄露
- 2.2 图片资源Bitmap相关
- 2.3 内存抖动
- 2.4 代码质量 & 数量
- 2.5 常见使用
- 额外小技巧
- 内存优化总结
- 参考资料
一、稳定性
影响Android
应用稳定性的原因有很多,主要是:应用崩溃(Crash)
、应用无响应(ANR)
这2个错误的结果将导致程序无法使用
ApplicationNotResponding
ApplicationNotResponding
(应用程序无响应)是卡死在一个页面。Application(应用)在5s内未响应用户输入事件(如按键or触摸),广播接收器(BroadcastReceiver)在10秒内未完成相关的处理,服务(Service)在20秒内无法处理完成,会出现对话框让用户选择等待或强制关闭。
- 优化原理
尽量避免应用程序出现ANR
情况 - 优化方案
使用多线程,将大量 & 耗时操作放在多线程中执行
- 多线程的方式 包括:
AsyncTask
、继承 Thread类
、实现 Runnable接口
、Handler消息机制
、HandlerThread
等
- 注:实际开发中,当一个进程发生了ANR后,系统会在 /data/anr目录下创建一个文件
traces.txt
,通过分析该文件可定位出ANR的原因
Crash
- 优化原理
应用崩溃Crash
很多情况是因为 内存溢出,即OOM
;故 需避免出现OOM
现象
内存溢出 简介:OOM(Out Of Memory)指应用程序所需的内存 超出了 系统为其分配的内存限额的现象。当应用程序中出西安内存泄露较多、不正常使用内存等情况时,容易导致应用程序所需的内存 超出了 系统为其分配的内存限额。会导致应用崩溃(Crash)。
解决方案:内存优化
稳定性总结
二、内存优化
定义:优化处理 应用程序的内存使用、空间占用
作用
避免因不正确使用内存 & 缺乏管理,从而出现 内存泄露(ML)
、内存溢出(OOM)
、内存空间占用过大 等问题,最终导致应用程序崩溃(Crash
)
1. 储备知识:Android 内存管理机制
1.1 简介
Android 内存管理机制 : 是对 进程、对象、变量 进行的内存 分配和回收 的机制。
Android 内存管理机制中负责 进程内存 的角色是 Application Framework
和 Linux内核
。负责 对象、变量内存 的角色是 Dalvik虚拟机
。
下面,将针对回收 进程、对象 、变量的内存分配 & 回收进行详细讲解
1.2 针对进程的内存策略
a. 内存分配策略
由 ActivityManagerService
集中管理 所有进程的内存分配
b. 内存回收策略
- 步骤1:
Application Framework
决定回收的进程类型
Android中的进程 是托管的;当进程空间紧张时,会 按进程优先级低->>高的顺序 自动回收进程
Android将进程分为5个优先等级,具体如下:
- 步骤2:
Linux
内核真正回收具体进程
ActivityManagerService
对 所有进程进行评分(评分存放在变量adj
中)- 更新评分到
Linux
内核 - 由
Linux
内核完成真正的内存回收
此处仅总结流程,这其中的复杂过程,需要研究系统源码ActivityManagerService.java
1.3 针对对象、变量的内存策略
Android
的对于对象、变量的内存策略同Java
- 内存管理 = 对象 / 变量的内存分配 + 内存释放
下面,将详细讲解内存分配 & 内存释放策略
a. 内存分配策略
- 对象 / 变量的内存分配 由程序自动 负责
- 共有3种:静态分配、栈式分配、 & 堆式分配,分别面向静态变量、局部变量 & 对象实例
- 具体介绍如下
内存分配策略 | 使用的内存空间 | 存储的数据 | 分配策略描述 |
---|---|---|---|
静态分配 | 方法区(静态存储区) | 已经被虚拟机加载的 类信息、常量、静态变量 | 程序编译时已分配好 并存在于程序的整个运行期间(不回收) |
栈式分配 | 栈区(Stack) | 方法执行时的局部变量(数据类型、对象的引用)(以帧栈的形式) | 1. 方法执行时,定义局部变量由程序在栈中分配内存 |
- 方法执行结束/超出变量域时,帧栈自动释放该部分内存
- 效率高(因为栈内存分配运算内置于处理器的指令集中)
- 分配的内存容量有限 |
| 堆式分配(动态内存分配) | 堆区(Heap) | Java对象的实例 与 实例内的成员变量
也就是关键字new出来的对象
实例的成员变量 = 基本数据类型、引用和引用的对象实体 | 1. 创建对象实例时,由程序分配(由Java垃圾回收管理器自动管理,不使用时则回收) - 在堆中创建1个对象或数组与在栈中定义一个引用变量 等于这个数组或对象在堆内存中的首地址
- 通过引用变量来访问堆内存中的对象或数组 |
注:用1个实例讲解 内存分配
public class Sample { // 该类的实例对象的成员变量s1、mSample1 与 指向对象存放在堆内存中int s1 = 0;Sample mSample1 = new Sample(); // 方法中的**局部变量s2、mSample2存放在 栈内存**// 变量mSample2所指向的**对象实例存放在 堆内存**public void method() { int s2 = 0;Sample mSample2 = new Sample();}
}// 变量mSample3的**引用存放在栈内存中**// 变量mSample3所指向的**对象实例存放在堆内存**// 该实例的成员变量s1、mSample1也存放在堆内存中Sample mSample3 = new Sample();
b. 内存释放策略
- 对象 / 变量的内存释放 由Java垃圾回收器(GC) / 帧栈 负责
- 此处主要讲解对象分配(即堆式分配)的内存释放策略 = Java垃圾回收器(GC)
静态分配不需释放、栈式分配仅 通过帧栈自动出、入栈,
- Java垃圾回收器(GC)的内存释放 = 垃圾回收算法,主要包括:
- 标记-清除算法
- 复制算法
- 标记-整理算法
- 分代收集算法
- 具体介绍如下
算法名称 | 算法思想 | 优点 | 缺点 | 应用场景 |
---|---|---|---|---|
标记-清除算法 | 标记阶段:标记出所有需要回收的对象 | |||
清楚阶段:统一清除(回收)所有被标记的对象 | 实现简单 | 效率问题:标记和清除两个过程效率不高 | ||
空间问题:标记-清楚后,会产生大量不连续的内存碎片 | 对象存活率较低 并且 垃圾回收行为频率低(如老年代) | |||
复制算法 | 将内存分为大小相等的两块,每次使用其中一块 | |||
当使用的这块内存用完,就将这块内存上还存活的对象复制到另一块内存上 | ||||
将使用的那块内存一次清理掉 | 解决了标记清除算法清除效率低的问他,(每次仅回收内存一半区域 ) | |||
解决了标记清除算法空间产生不连续内存碎片的问题,(将已使用内存上的存活对象移动到栈顶的指针,按顺序分配内存) | 每次使用内存缩小为原来的一半 | |||
当对象存活率较高的情况下需要做很多复制操作,效率会变低 | 对象存活率较低 并且 需要频繁进行垃圾回收的区域(如新年代) | |||
标记整理算法 | 标记阶段:标记出所有需要回收的对象 | |||
整理阶段:所有存活对象都向一端移动 | ||||
清除阶段:统一清除(回收)端以外的对象 | 解决了标记清除算法中清楚效率低等问题:一次清除端外区域 | |||
解决了标记清除算法中空间产生不连续内存碎片问题:将已使用内存上的存活对象移动到栈顶的指针,按顺序分配内存即可 | 步骤繁多:标记、整理、清除 | 对象存活率较低并且垃圾回收行为频率低(如老年代) | ||
分代收集算法 | 根据对象存货周期不同将Java堆内存分为:新生代与老年代 | |||
新生代:对象存活率低 并且垃圾回收行为频率高 | ||||
新生代:采用复制算法 | ||||
老年代:采用标记-清除算法、标记-整理算法 | ||||
效率高、空间利用率高;根据不同区域特点选择不同垃圾收集算法 | 虚拟机基本都采用这种算法 |
2. 常见的内存问题 & 优化方案
常见的内存问题如下
- 内存泄露
- 内存抖动
- 图片Bitmap相关
- 代码质量 & 数量
- 日常不正确使用
下面,我将详细分析每项的内存问题 & 给出优化方案
2.1 内存泄露
即 ML (Memory Leak
),指 程序在申请内存后,当该内存不需再使用 但 却无法被释放 & 归还给 程序的现象
对应用程序的影响:容易使得应用程序发生内存溢出,即 OOM
内存溢出 简介:
OOM(Out Of Memory)指应用程序所需的内存 超出了 系统为其分配的内存限额的现象。当应用程序中出现内存泄露较多、不正常使用内存等情况时,容易导致应用程序所需的内存 超出了 系统为其分配的内存限额。会导致应用崩溃(Crash)。
- 发生内存泄露的本质原因:本该回收的对象因为某些原因而不能被回收,从而继续停留在堆内存中。
”本该被回收“指的是该对象已不需再被使用。
”某些原因“指的是有另外一个正在使用的对象持有它的引用,即无意识地持有对象。
**内存溢出本质原因是:**持有引用者 的生命周期>被引用者的生命周期,从而当后者需结束生命周期去销毁时,无法被正确回收。
- 常见内存泄露原因
- 集合类
Static
关键字修饰的成员变量- 非静态内部类 / 匿名类
- 资源对象使用后未关闭
- 优化方案:内存泄露
2.2 图片资源Bitmap相关
- 优化原因即 为什么要优化图片
Bitmap
资源?
因为Android系统分配给每个应用程序的内存有限,图片资源(Bitmap)非常消耗内存,很多情况下,图片所占的内存占整个App内存的大部分 - 如果对
Bitmap
的使用或内存管理稍有不当,就可能引发内存溢出(OutOfMemoryError),容易造成应用崩溃(Crash)
优化方向
主要 从 以下方面优化图片Bitmap资源的使用 & 内存管理
2.3 内存抖动
- 简介
内存抖动:内存大小不断浮动的现象。
是由于程序频繁地分配内存 与 垃圾收集器(GC)频繁地回收内存造成的。深层次原因是大量、临时的小对象频繁创建。
由于大量、临时的小对象频繁创建会导致内存碎片,使得当需分配内存时,虽总体上还是有剩余内存可分配,但这些内存不连续,导致无法整块分配。系统视为内存不够,会导致卡顿,甚至导致内存溢出OOM。
- 优化方案尽量避免频繁创建大量、临时的小对象
2.4 代码质量 & 数量
- 优化原因
代码本身的质量(如 数据结构、数据类型等) & 数量(代码量的大小)可能会导致大量的内存问题,如占用内存大、内存利用率低等 - 优化方案主要从代码总量、数据结构、数据类型、 & 数据对象引用 方面优化,具体如下
优化方向 | 优化方案 | 具体描述 | 备注 |
---|---|---|---|
代码数据总量 | 不必要的类、对象和功能库会带来巨大内存开销 | 减少不必要的类和对象 | |
减少引入不必要的库 | |||
使用代码混淆 | 代码混淆的作用:去除无用的代码 并 通过语义模糊 重命名类、字段和方法。从而缩小、优化代码,使得代码更简洁、更少量的RAM映射页。 | ||
尽可能减少数据体积大小 | 通过序列化数据从而减少数据体积大小(Google出品的ProtocolBuffer,可节省30%的数据大小) | 慎用Sharedprefercnce | |
因对于同一个sp,会将整个xml文件载入内存,容易出现为了读一个配置,就将几百k的数据读进内存。 | |||
数据结构 | 使用性能高的数据结构 | 利用Android优化后的数据容器取代传统的HashMap | ArrayMap和SparseArray是Android的系统API |
专门为移动设备定制,用于取代HashMap达到节省内存的目的 | |||
(a.传统的HashMap在内存上的实现十分低效的原因,需为map中每项在内存中建立映射关系 | |||
b.SparseArray类高效的原因,避免系统中需自动封箱(autobox)的key) | |||
数据类型 | 使用占用内存小的数据类型 | 尽量避免使用枚举类型 | 枚举变量占用内存大,比直接使用int类型多占用两倍2内存 |
数据对象引用 | 根据不同的应用场景,选择不同的引用类型(强、软、弱、虚) | 强引用:该变量不希望被垃圾回收器回收 | |
软引用:缓存机制(实现内存敏感的数据缓存,如图片、网页缓存等) | |||
弱引用:防止内存泄露、保护对象引用 | |||
虚引用:跟踪对象被垃圾回收器回收的活动 |
2.5 常见使用
- 优化原因
一些常见使用也可能引发大量的内存问题,下面详细介绍。 - 优化方案
注:
还有1个内存优化的终极方案:调大 虚拟机Dalvik
的堆内存大小
即 在AndroidManifest.xml
的application
标签中增加一个android:largeHeap
属性(值 =true
),从而通知虚拟机 应用程序需更大的堆内存
但不建议 & 不鼓励该做法
额外小技巧
- 技巧1:获取当前可使用的内存大小
调用 **ActivityManager.getMemoryClass()
**方法可获取当前应用可用的内存大小(单位 = 兆) - 技巧2:获取当前的内存使用情况
在应用生命周期的任何阶段,调用onTrimMemory()
获取应用程序 当前内存使用情况(以内存级别进行识别),可根据该方法返回的内存紧张级别参数 来释放内存
Android 4.0 后提供的一个API
- 技巧3:当视图变为隐藏状态时,则释放内存
当用户跳转到不同的应用 & 视图不再显示时, 应释放应用视图所占的资源
注:此时释放所占用的资源能显著的提高系统的缓存处理容量
具体操作:实现当前Activity
类的onTrimMemory()
后,当用户离开视图时会得到通知;若得到返回的参数 = TRIM_MEMORY_UI_HIDDEN
即代表视图变为隐藏状态,则可释放视图所占用的资源.
内存优化总结
参考资料
https://carsonho.blog.csdn.net/article/details/79708444
Android开发艺术探索
Android性能优化学习记录(二)稳定性与内存优化相关推荐
- 【朝花夕拾】Android性能篇之(二)Java内存分配
前言 原文:[朝花夕拾]Android性能篇之(二)Java内存分配 在内存方面,相比于C/C++程序员,咱们java系程序员算是比较幸运的,因为对于内存的分配和回收,都交给 ...
- Android动画学习记录二(属性动画、估值器和插值器)
Android动画学习记录二(属性动画.估值期和插值器) Android动画学习记录二(属性动画.估值期和插值器) Android动画学习记录二(属性动画.估值期和插值器) 一.补间动画缺陷 二.属性 ...
- Android OpenGl Es 学习(二):定义顶点和着色器
概述 这是一个新的系列,学习OpengGl Es,其实是<OpenGl Es 应用开发实践指南 Android卷>的学习笔记,感兴趣的可以直接看这本书,当然这个会记录自己的理解,以下只作为 ...
- MySQL学习记录 (二) ----- SQL数据查询语句(DQL)
相关文章: <MySQL学习记录 (一) ----- 有关数据库的基本概念和MySQL常用命令> <MySQL学习记录 (二) ----- SQL数据查询语句(DQL)> &l ...
- HTML学习记录二:html标签(五):超链接标签
HTML学习记录二:html标签(五):超链接标签 一.超链接标签写法 二.超链接标签的属性 三.超链接的锚点用法 四.链接分类 一.超链接标签写法 在 HTML 标签中, 标签用于定义超链接,作用是 ...
- 大数据之spark学习记录二: Spark的安装与上手
大数据之spark学习记录二: Spark的安装与上手 文章目录 大数据之spark学习记录二: Spark的安装与上手 Spark安装 本地模式 Standalone 模式 基本配置 步骤1: 复制 ...
- Linux基础优化方法(二)———系统安全相关优化:防火墙和selinux
Linux基础优化方法(二)---系统安全相关优化:防火墙和selinux 一.系统防火墙服务优化 1.CentOS 6 ①.查看防火墙服务状态 ②.临时关闭防火墙服务 ③.永久关闭防火墙服务 2.C ...
- SQL Server 2014 内存优化表(1)实现内存优化表
内存优化表(Memory-Optimized Tables)是SQL Server 2014的新特性,目前仅适用于评估版(Evaluation Edition).开发版(Developer Editi ...
- Mysql 优化(学习笔记二十)
https://blog.csdn.net/steven_liwen/article/details/53188411 运维角度mysql优化:https://www.cnblogs.com/shen ...
- 凸优化学习-(二十九)有约束优化算法——增广拉格朗日法、交替方向乘子法(ADMM)
凸优化学习 我们前面说过,拉格朗日法在实际中应用不大.为什么呢?因为 α \alpha α的取值很难取,这就导致拉格朗日法鲁棒性很低,收敛很慢,解很不稳定.于是就有了今天的增广拉格朗日法和ADMM. ...
最新文章
- 南京大学人工智能学院院长周志华:培养有源头创新力的人才!
- pytorch中load和load_state_dict区别
- 3、SpringBoot整合MyBatis注解版及配置文件版
- linux c之fdopen(int fd, const char *type)使用总结
- 报名照片审核处理工具_太浦军考|2020年文职人员报名照片审核程序,照片处理工具应该如何使用?...
- python使用函数目的_Python函数的概念和使用
- MPLS ××× Carrier Supporting Carrier Option AB(二)
- arraylist线程安全吗_Java中的List你真的会用吗?不会用的话请收藏我的这篇文章...
- 可以解压日文的软件_日文换成中文字体就不好看?我偏不信这个邪!
- 运算放大器分析----虚短和虚断简单计算
- k8s+containerd+kata-containers 安装
- Vue 项目使用 又拍云 云存储服务
- 记在2019,winter is coming
- 快速了解元宇宙的 7 层产业链
- 女子花2万元雇友人杀逝世女街坊
- 【AutoCAD For Mac 手动删除步骤】
- 基于C++的AGV机器人无线控制
- 游戏开发人员推荐书单
- 应急响应的整体思路和基本流程
- 软件和 IT 服务成美国收入最高行业;黑客组织 OurMine 宣称攻陷维基解密网站
热门文章
- win8/8.1安装不了.net 4.6.2版本的解决方法
- 计算机桌面图标右上角出现双箭头符号,电脑桌面图标有箭头怎么办 电脑桌面图片箭头去掉方法【图文】...
- 2017_Generating high-quality crowd density maps using contextual pyramid cnns
- 计算机id和密码怎么查,忘记Apple ID账号和密码怎么办?
- 信息系统项目管理师——历年论文题目2012年-2020年
- 【黑灰产犯罪研究】恶意点击
- Python学习:使用pycharm运行py文件报错系统找不到指定的路径
- mipi的dsi全称_MIPI-DSI/CSI协议介绍
- 什么是边界扫描(boundary scan)?
- Python运行环境详细总结