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 情况
  • 优化方案
    使用多线程,将大量 & 耗时操作放在多线程中执行
  1. 多线程的方式 包括:AsyncTask继承 Thread类实现 Runnable接口Handler消息机制HandlerThread
  1. 注:实际开发中,当一个进程发生了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 FrameworkLinux内核。负责 对象、变量内存 的角色是 Dalvik虚拟机

下面,将针对回收 进程、对象 、变量的内存分配 & 回收进行详细讲解

1.2 针对进程的内存策略

a. 内存分配策略
ActivityManagerService 集中管理 所有进程的内存分配

b. 内存回收策略

  • 步骤1:Application Framework 决定回收的进程类型
    Android中的进程 是托管的;当进程空间紧张时,会 按进程优先级低->>高的顺序 自动回收进程
    Android将进程分为5个优先等级,具体如下:

  • 步骤2:Linux 内核真正回收具体进程
  1. ActivityManagerService 对 所有进程进行评分(评分存放在变量adj中)
  2. 更新评分到Linux 内核
  3. Linux 内核完成真正的内存回收
    此处仅总结流程,这其中的复杂过程,需要研究系统源码ActivityManagerService.java

1.3 针对对象、变量的内存策略

  • Android的对于对象、变量的内存策略同 Java
  • 内存管理 = 对象 / 变量的内存分配 + 内存释放

下面,将详细讲解内存分配 & 内存释放策略

a. 内存分配策略

  • 对象 / 变量的内存分配 由程序自动 负责
  • 共有3种:静态分配、栈式分配、 & 堆式分配,分别面向静态变量、局部变量 & 对象实例
  • 具体介绍如下
内存分配策略 使用的内存空间 存储的数据 分配策略描述
静态分配 方法区(静态存储区) 已经被虚拟机加载的 类信息、常量、静态变量 程序编译时已分配好 并存在于程序的整个运行期间(不回收)
栈式分配 栈区(Stack) 方法执行时的局部变量(数据类型、对象的引用)(以帧栈的形式) 1. 方法执行时,定义局部变量由程序在栈中分配内存
  1. 方法执行结束/超出变量域时,帧栈自动释放该部分内存
  2. 效率高(因为栈内存分配运算内置于处理器的指令集中)
  3. 分配的内存容量有限 |
    | 堆式分配(动态内存分配) | 堆区(Heap) | Java对象的实例 与 实例内的成员变量
    也就是关键字new出来的对象
    实例的成员变量 = 基本数据类型、引用和引用的对象实体 | 1. 创建对象实例时,由程序分配(由Java垃圾回收管理器自动管理,不使用时则回收)
  4. 在堆中创建1个对象或数组与在栈中定义一个引用变量 等于这个数组或对象在堆内存中的首地址
  5. 通过引用变量来访问堆内存中的对象或数组 |

注:用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)的内存释放 = 垃圾回收算法,主要包括:
  1. 标记-清除算法
  2. 复制算法
  3. 标记-整理算法
  4. 分代收集算法
  • 具体介绍如下
算法名称 算法思想 优点 缺点 应用场景
标记-清除算法 标记阶段:标记出所有需要回收的对象
清楚阶段:统一清除(回收)所有被标记的对象 实现简单 效率问题:标记和清除两个过程效率不高
空间问题:标记-清楚后,会产生大量不连续的内存碎片 对象存活率较低 并且 垃圾回收行为频率低(如老年代)
复制算法 将内存分为大小相等的两块,每次使用其中一块
当使用的这块内存用完,就将这块内存上还存活的对象复制到另一块内存上
将使用的那块内存一次清理掉 解决了标记清除算法清除效率低的问他,(每次仅回收内存一半区域 )
解决了标记清除算法空间产生不连续内存碎片的问题,(将已使用内存上的存活对象移动到栈顶的指针,按顺序分配内存) 每次使用内存缩小为原来的一半
当对象存活率较高的情况下需要做很多复制操作,效率会变低 对象存活率较低 并且 需要频繁进行垃圾回收的区域(如新年代)
标记整理算法 标记阶段:标记出所有需要回收的对象
整理阶段:所有存活对象都向一端移动
清除阶段:统一清除(回收)端以外的对象 解决了标记清除算法中清楚效率低等问题:一次清除端外区域
解决了标记清除算法中空间产生不连续内存碎片问题:将已使用内存上的存活对象移动到栈顶的指针,按顺序分配内存即可 步骤繁多:标记、整理、清除 对象存活率较低并且垃圾回收行为频率低(如老年代)
分代收集算法 根据对象存货周期不同将Java堆内存分为:新生代与老年代
新生代:对象存活率低 并且垃圾回收行为频率高
新生代:采用复制算法
老年代:采用标记-清除算法、标记-整理算法
效率高、空间利用率高;根据不同区域特点选择不同垃圾收集算法 虚拟机基本都采用这种算法

2. 常见的内存问题 & 优化方案

常见的内存问题如下

  1. 内存泄露
  2. 内存抖动
  3. 图片Bitmap相关
  4. 代码质量 & 数量
  5. 日常不正确使用
    下面,我将详细分析每项的内存问题 & 给出优化方案

2.1 内存泄露

即 ML (Memory Leak),指 程序在申请内存后,当该内存不需再使用 但 却无法被释放 & 归还给 程序的现象

对应用程序的影响:容易使得应用程序发生内存溢出,即 OOM

内存溢出 简介:
OOM(Out Of Memory)指应用程序所需的内存 超出了 系统为其分配的内存限额的现象。当应用程序中出现内存泄露较多、不正常使用内存等情况时,容易导致应用程序所需的内存 超出了 系统为其分配的内存限额。会导致应用崩溃(Crash)。

  • 发生内存泄露的本质原因:本该回收的对象因为某些原因而不能被回收,从而继续停留在堆内存中。

”本该被回收“指的是该对象已不需再被使用。
”某些原因“指的是有另外一个正在使用的对象持有它的引用,即无意识地持有对象。
**内存溢出本质原因是:**持有引用者 的生命周期>被引用者的生命周期,从而当后者需结束生命周期去销毁时,无法被正确回收。

  • 常见内存泄露原因

    1. 集合类
    2. Static关键字修饰的成员变量
    3. 非静态内部类 / 匿名类
    4. 资源对象使用后未关闭
  • 优化方案:内存泄露

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.xmlapplication标签中增加一个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性能优化学习记录(二)稳定性与内存优化相关推荐

  1. 【朝花夕拾】Android性能篇之(二)Java内存分配

    前言       原文:[朝花夕拾]Android性能篇之(二)Java内存分配        在内存方面,相比于C/C++程序员,咱们java系程序员算是比较幸运的,因为对于内存的分配和回收,都交给 ...

  2. Android动画学习记录二(属性动画、估值器和插值器)

    Android动画学习记录二(属性动画.估值期和插值器) Android动画学习记录二(属性动画.估值期和插值器) Android动画学习记录二(属性动画.估值期和插值器) 一.补间动画缺陷 二.属性 ...

  3. Android OpenGl Es 学习(二):定义顶点和着色器

    概述 这是一个新的系列,学习OpengGl Es,其实是<OpenGl Es 应用开发实践指南 Android卷>的学习笔记,感兴趣的可以直接看这本书,当然这个会记录自己的理解,以下只作为 ...

  4. MySQL学习记录 (二) ----- SQL数据查询语句(DQL)

    相关文章: <MySQL学习记录 (一) ----- 有关数据库的基本概念和MySQL常用命令> <MySQL学习记录 (二) ----- SQL数据查询语句(DQL)> &l ...

  5. HTML学习记录二:html标签(五):超链接标签

    HTML学习记录二:html标签(五):超链接标签 一.超链接标签写法 二.超链接标签的属性 三.超链接的锚点用法 四.链接分类 一.超链接标签写法 在 HTML 标签中, 标签用于定义超链接,作用是 ...

  6. 大数据之spark学习记录二: Spark的安装与上手

    大数据之spark学习记录二: Spark的安装与上手 文章目录 大数据之spark学习记录二: Spark的安装与上手 Spark安装 本地模式 Standalone 模式 基本配置 步骤1: 复制 ...

  7. Linux基础优化方法(二)———系统安全相关优化:防火墙和selinux

    Linux基础优化方法(二)---系统安全相关优化:防火墙和selinux 一.系统防火墙服务优化 1.CentOS 6 ①.查看防火墙服务状态 ②.临时关闭防火墙服务 ③.永久关闭防火墙服务 2.C ...

  8. SQL Server 2014 内存优化表(1)实现内存优化表

    内存优化表(Memory-Optimized Tables)是SQL Server 2014的新特性,目前仅适用于评估版(Evaluation Edition).开发版(Developer Editi ...

  9. Mysql 优化(学习笔记二十)

    https://blog.csdn.net/steven_liwen/article/details/53188411 运维角度mysql优化:https://www.cnblogs.com/shen ...

  10. 凸优化学习-(二十九)有约束优化算法——增广拉格朗日法、交替方向乘子法(ADMM)

    凸优化学习 我们前面说过,拉格朗日法在实际中应用不大.为什么呢?因为 α \alpha α的取值很难取,这就导致拉格朗日法鲁棒性很低,收敛很慢,解很不稳定.于是就有了今天的增广拉格朗日法和ADMM. ...

最新文章

  1. 南京大学人工智能学院院长周志华:培养有源头创新力的人才!
  2. pytorch中load和load_state_dict区别
  3. 3、SpringBoot整合MyBatis注解版及配置文件版
  4. linux c之fdopen(int fd, const char *type)使用总结
  5. 报名照片审核处理工具_太浦军考|2020年文职人员报名照片审核程序,照片处理工具应该如何使用?...
  6. python使用函数目的_Python函数的概念和使用
  7. MPLS ××× Carrier Supporting Carrier Option AB(二)
  8. arraylist线程安全吗_Java中的List你真的会用吗?不会用的话请收藏我的这篇文章...
  9. 可以解压日文的软件_日文换成中文字体就不好看?我偏不信这个邪!
  10. 运算放大器分析----虚短和虚断简单计算
  11. k8s+containerd+kata-containers 安装
  12. Vue 项目使用 又拍云 云存储服务
  13. 记在2019,winter is coming
  14. 快速了解元宇宙的 7 层产业链
  15. 女子花2万元雇友人杀逝世女街坊
  16. 【AutoCAD For Mac 手动删除步骤】
  17. 基于C++的AGV机器人无线控制
  18. 游戏开发人员推荐书单
  19. 应急响应的整体思路和基本流程
  20. 软件和 IT 服务成美国收入最高行业;黑客组织 OurMine 宣称攻陷维基解密网站

热门文章

  1. win8/8.1安装不了.net 4.6.2版本的解决方法
  2. 计算机桌面图标右上角出现双箭头符号,电脑桌面图标有箭头怎么办 电脑桌面图片箭头去掉方法【图文】...
  3. 2017_Generating high-quality crowd density maps using contextual pyramid cnns
  4. 计算机id和密码怎么查,忘记Apple ID账号和密码怎么办?
  5. 信息系统项目管理师——历年论文题目2012年-2020年
  6. 【黑灰产犯罪研究】恶意点击
  7. Python学习:使用pycharm运行py文件报错系统找不到指定的路径
  8. mipi的dsi全称_MIPI-DSI/CSI协议介绍
  9. 什么是边界扫描(boundary scan)?
  10. Python运行环境详细总结