Android笔记--内存管理

news2024/11/20 1:38:26

        内存(Memory)是计算机的重要部件,也称主存储器,它用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。Android中,内存是如何分配的?当启动一个android程序时,会启动一个dalvik vm进程,系统会给它分配固定的虚拟内存空间(16M,32M不定),这块内存空间会映射到ram上某个区域。然后这个android程序就会运行在这块空间上。安卓采用弹性内存分配机制。也就是说一开始并不会分配太多的内存。而是给每一个APP的进程分配一个小额的量。这个小额的量跟手机的内存大小有关。当进程内存不够的时候,安卓会再分配一些内存给各个进程,它是有限度的,如果超过这个限度,则会出现OOM异常。

Android中应用是跑在 Android虚拟机中,它对jvm进行了兼容,Java运行时的内存模型

 方法区:与Java一样,是各个线程所共享的,用于存储已被虚拟机加载类信息、常量、静态变量、即时编译器编译后的代码等数据。

Java堆:是虚拟机管理内存中最大的一块,被所有线程共享,该区域用于存放对象实例,Java堆是内存回收的主要区域。

Java虚拟机栈:线程私有的,其生命周期和线程一致,每个方法执行时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。

本地方法栈:存放native方法的相关信息

程序计数器:一块较小内存区域,指向当前所执行的字节码。

我们开发的应用时,一般程序里所占内存区域是堆区,这一块区域也是经常导致内存紧张的区域,所以有专门对这一块设计了垃圾回收机制。常见垃圾回收算法如下:

1 引用计数法 记录每个引用的被引用个数,当引用个数为0时代表成为垃圾,应该被清理。

优点: 实现简单 引用减少至0时,实时回收内存,内存利用率高 回收操作可并发运行,无需暂停应用线程

缺点: 1 无法解决环状引用,如a引用b,b引用a。两个都是垃圾却不会被清理 2 需要维护计数器

Java四种引用

强引用
是指创建一个对象并把这个对象赋给一个引用变量。
强引用有引用变量指向时永远不会被垃圾回收,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。

软引用(SoftReference)
一个对象具有软引用,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。

弱引用(WeakReference)
弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象

虚引用(PhantomReference)
虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期,在任何时候都可能被垃圾回收器回收。

Java中提供这四种引用类型主要有两个目的:
第一是可以让程序员通过代码的方式决定某些对象的生命周期;
第二是有利于JVM进行垃圾回收。

2 可达性分析法(根搜索算法) 确定根对象(GC ROOT),顺着根对象遍历,凡是被根对象直接或者间接引用的都不是垃圾,剩下就是垃圾。

优点: 1. 不存在循环引用问题 2. 不存在引用计数法的空间开销

缺点: 3. 内存利用率低(在GC回收内存前,垃圾对象占用的内存无法复用)

哪些对象可以作为Root对象?

1 方法区中静态属性引用的对象 2 方法区中常量引用的对象 3 本地方法栈中引用的对象(Native对象) 特征:它们的生命周期较长。

3 CMS(Concurrent Low Pause Collector) 一个老年代收集器,是JDK1.4后期开始引用的新GC收集器,CMS的一大特点,就是用两次短暂的暂停来代替串行整理算法时候的长暂停。使用算法:标记 - 清理.

初始标记 : 标记与 GC Roots 有引用链的对象 ; 该操作速度快 , 该步骤需要暂停用户线程 ;
并发标记 : GC Roots 追踪 , 从初始标记结果集合中标记出存活对象 , 不能保证所有的存活对象都被标记 ; 该步骤与应用程序并发执行 ;
重新标记 : 上一步并发标记 GC 线程与用户程序并发期间的标记有部分变化 , 修正这部分标记信息 , 之后暂停用户线程 , 开始标记 ; 该暂停操作要比初始标记步骤暂停时间长 ;
并发清除 : 回收所有 GC Roots 不可达对象 ;

CMS优点: 1 降低GC停顿时间,关注应用响应速度;

CMS缺点: 1、内存碎片。由于使用了 标记-清理 算法,该算法不会对内存碎片进行清理,导致内存空间中会产生内存碎片。 2、需要更多的CPU资源。由于使用了并发处理,很多情况下都是GC线程和应用线程并发执行的,这样就需要占用更多的CPU资源。

4 CC(Concurrent Copying) Android 8开始默认垃圾收集器,CC 通过在不暂停应用线程的情况下并发复制对象来执行堆碎片整理。这是在读取屏障的帮助下实现的,读取屏障会拦截来自堆的引用读取,无需应用开发者进行任何干预。GC 只有一次很短的暂停,对于堆大小而言,该次暂停在时间上是一个常量。

优点:降低GC停顿时间

Android内存回收机制

        默认进程回收机制: 当系统内存不足时,系统将激活内存回收过程。为了不因内存回收影响用户体验(如杀死当前的活动进程), 回收优先级: Android 基于进程中运行的组件及其状态规定了默认的五个回收优先级:

IMPORTANCE_FOREGROUND:前台进程,目前正在屏幕上显示的进程和一些系统进程。 IMPORTANCE_VISIBLE:可见进程,可见进程是一些不再前台,但用户依然可见的进程,比如输入法、天气、时钟等。

IMPORTANCE_SERVICE:服务进程,拨号、邮件存储之类的。 IMPORTANCE_BACKGROUND:后台进程,启动后被切换到后台的进程。

IMPORTANCE_EMPTY:没有任何东西在内运行的进程,有些程序,比如BTE,在程序退出后,依然会在进程中驻留一个空进程,这个进程里没有任何数据在运行,作用往往是提高该程序下次的启动速度或者记录程序的一些历史信息。

Low Memory Killer机制

         在系统内存减少到达一个阈值时,系统就会开始根据进程的优先级来进行回收机制杀掉一部分进程来释放出内存供后面需要启动的App使用。这套回收内存的机制就叫Low Memory Killer。Linux内核分配给每个系统进程的一个值,叫做oom_adj值。此值越大,进程的优先级越低,越容易被回收,普通应用进程的oom_adj值是>=0,而系统进程的oom_adj值是<0的。

      当内存不足,触发内存阈值时,出现两个普通应用存在相同的adj值时,系统应该先回收哪一个应用进程? 答:占用内存较大的那个

内存泄露

        指程序在申请内存后,无法释放已申请的内存空间,导致系统无法及时回收内存并且分配给其他进程使用。通常少次数的内存无法及时回收并不会到程序造成什么影响,但是如果在内存本身就比较少获取多次导致内存无法正常回收时,就会导致内存不够用,最终导致内存溢出。

内存溢出(OOM)

        指程序申请内存时,没有足够的内存供申请者使用,导致数据无法正常存储到内存中。

内存抖动

          主要是由于频繁的创建和销毁对象导致的,这种循环往复的状态就叫做内存抖动Memory Churn;

内存泄露与内存溢出(OOM)的关系以及区别

关系:内存泄露最终会导致内存溢出,由于系统中的内存是有限的,如果过度占用资源而不及时释放,最后会导致内存不足,从而无法给所需要存储的数据提供足够的内存,从而导致内存溢出。 区别:内存泄露是由于GC无法及时或者无法识别可以回收的数据进行及时的回收,导致内存的浪费;内存溢出是由于数据所需要的内存无法得到满足,导致数据无法正常存储到内存中。内存泄露的多次表现就是会导致内存溢出。

内存溢出与内存抖动的关系

 如果说分配的频率大于回收的频率,那么最终就会导致OOM的发生。

Android中如何进行内存优化 ?

1.避免在Application和Activity的onCreate方法中做过多工作,这会占用过多内存。可以将不必要的初始化工作放到onStart或延迟加载。
2.优化布局,减少视图层级,可以通过merge标签减少不必要的ViewGroup,过多View会增加内存占用。
3.单例里不要持有Activity引用。
4. Bitmap使用低内存的解析模式,如RGB565,对Bitmap进行inSampleSize压缩,在Bitmap不被使用的时候recycle掉。

Android中为什么要进行内存优化 ?

1 避免不合理使用内存导致 GC 次数增多,从而导致应用发生卡顿。
2 降低应用由于内存过大被 LMK 机制杀死的概率。
3 防止应用发生 OOM。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/591426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux条件变量知识点总结

与条件变量相关API 条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时&#xff0c;允许线程以无竞争的方式等待特定的条件发生。 条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量&#xff0c;其他线程…

chatgpt赋能python:Python中的“5“+“5“:了解运算符重载和字符串拼接

Python中的 “5”“5”: 了解运算符重载和字符串拼接 Python中的运算符重载允许我们自定义类型的操作符行为。当我们使用加号运算符将两个对象相加时&#xff0c;Python会动态地确定该使用哪种类型的操作符行为。在使用字符串时&#xff0c;加号可以用于字符串的连接&#xff…

【编译、链接、装载二】/lib/ld64.so.1: bad ELF interpreter: 没有那个文件或目录

【编译和链接二】bash: ./test.out: /lib/ld64.so.1: bad ELF interpreter: 没有那个文件或目录 一、问题起因二、ldd查看三、解决方案一&#xff1a;使用gcc链接四、查找其他解决方案五、解决方案二&#xff1a;软链接 bash: ./test.out: /lib/ld64.so.1: bad ELF interpreter…

SpringBoot框架总结

一、SpringBoot框架的概念 1、传统框架的弊端 例如传统的SSM框架整合了MyBatis、Spring、SpringMVC框架&#xff0c;但其需要繁琐且重复的配置使程序员很是痛苦 2、SpringBoot框架 SpringBoot框架在传统框架的基础上对其进一步封装&#xff0c;只需要一些简单的配置&#x…

MySQL第二章、数据库基础

回顾&#xff1a; 目录 一、数据库的操作 1.1创建数据库 1.2显示当前数据库 1.3使用数据库 1.4删除数据库 二、常用数据类型 2.1数值类型&#xff08;分为整型和浮点型&#xff09; 2.2字符串类型 2.3 日期类型 三、表的操作 ​编辑 3.1创建表 3.2查看表结构 ​编…

网络攻防技术--论文阅读--《基于自动数据分割和注意力LSTM-CNN的准周期时间序列异常检测》

英文题目&#xff1a;Anomaly Detection in Quasi-Periodic Time Series based on Automatic Data Segmentation and Attentional LSTM-CNN 论文地址&#xff1a;Anomaly Detection in Quasi-Periodic Time Series Based on Automatic Data Segmentation and Attentional LST…

chatgpt赋能python:Python中清空代码的几种方法

Python中清空代码的几种方法 在Python编程中&#xff0c;清空代码是一个很常见的需求。清空代码指的是在某些情况下&#xff0c;需要将已经定义的变量或内存中存储的对象清除&#xff0c;以便后续使用。在本文中&#xff0c;我们将介绍Python中常用的几种清空代码的方法。 方…

chatgpt赋能python:Python中等待几秒代码:让你的程序更高效

Python中等待几秒代码&#xff1a;让你的程序更高效 在编写Python程序时&#xff0c;有时我们需要让程序等待几秒钟之后再继续执行。这个操作非常常见&#xff0c;尤其是在需要与API接口交互的时候。在本文中&#xff0c;我们将会介绍Python语言中等待几秒的相关知识&#xff…

如何使用Kali进行信息收集?

渗透测试即模拟黑客入侵的手段对目标网络进修安全测试&#xff0c;从而发现目标网络的漏洞&#xff0c;对目标网络进行安全加固与漏洞修复。 Kali 是一个基于 debian 的渗透测试平台&#xff0c;其中集成了很多常见的和不常见的渗透测试工具&#xff0c;如下图&#xff1a; 工…

linux(SystemV标准)进程间通信1

目录&#xff1a; 1.前言 2.共享内存 3.认识接口 ------------------------------------------------------------------------------------------------------------------------- 1.前言 我们之前学的什么匿名管道、命名管道通信都是基于文件的通信方式&#xff01;&#xf…

chatgpt赋能python:Python中的%怎么用

Python中的%怎么用 Python中的%是一个非常重要的运算符&#xff0c;也称为格式化运算符。它用于将一个值插入到另一个字符串中。在本文中&#xff0c;我们将深入了解Python中的%运算符的使用。 %运算符的语法 先看下%运算符的语法&#xff1a; string % values其中&#xf…

求图的最短路径长度的弗洛伊德(Floyd)算法

弗洛伊德算法的适用情况&#xff1a;弗洛伊德算法既可以用来求解有向网的最短路径长度&#xff0c;也可以用来求无向网的最短路径长度&#xff0c;但是对于图中出现负权环的情况&#xff0c;弗洛伊德无法的得到正确的答案 弗洛伊德的算法思想&#xff1a; 以此图为例讲解弗洛…

C语言杂七杂八

fget函数的用法 fgets() 函数用来从指定的文件中读取一个字符串&#xff0c;并保存到字符数组中。 str 为字符数组&#xff0c;n 为要读取的字符数目&#xff0c;fp 为文件指针。 char *fgets(char *str, int n, FILE *stream) 返回值&#xff1a;读取成功时返回字符数组首地…

python图像处理实战(一)—图像基础

&#x1f680;写在前面&#x1f680; &#x1f58a;个人主页&#xff1a;https://blog.csdn.net/m0_52051577?typeblog &#x1f381;欢迎各位大佬支持点赞收藏&#xff0c;三连必回&#xff01;&#xff01; &#x1f508;本人新开系列专栏—python图像处理 ❀愿每一个骤雨初…

Android12之service调试(一百五十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

C4D R26 渲染学习笔记 建模篇(3):生成器

文章目录 前文回顾介绍篇建模篇 生成器介绍生成器变形器搭配举例 生成器详细介绍细分曲面布料曲面 未完待续 前文回顾 介绍篇 C4D R26 渲染学习笔记&#xff08;1&#xff09;&#xff1a;C4D版本选择和初始UI框介绍 C4D R26 渲染学习笔记&#xff08;2&#xff09;&#xff…

微服务Spring Cloud 02------使用Eureka实现注册中心(1)

1.Eureka简介 Eureka是Spring Cloud中的一个负责服务注册与发现的组件。遵循着CAP理论中的A(可用性)和P(分区容错性)。 Eureka是Netflix中的一个开源框架。它和 Zookeeper、Consul一样&#xff0c;都是用于服务注册管理的&#xff0c;同样&#xff0c;Spring-Cloud 还集成了Zo…

Canvas画布基本功能及实现网页签名功能

canvas 简介 <canvas> 是 HTML5 新增的&#xff0c;一个可以使用脚本(通常为 JavaScript) 在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画&#xff0c;甚至可以进行实时视频处理和渲染。和所有 DOM 元素一样&#xff0c;拥有自己…

chatgpt赋能python:Python中累乘的作用和用法

Python中累乘的作用和用法 在Python编程语言中&#xff0c;累乘指的是连续乘法&#xff0c;或者说是一系列数字的乘积。累乘的概念非常简单&#xff0c;但是实际上它在编程中有着广泛的应用。 累乘在Python中的实现方式 Python中&#xff0c;累乘可以通过多种方式来实现&…

手写一个webpack插件(plugin)

熟悉 vue 和 react 的小伙伴们都知道&#xff0c;在执行过程中会有各种生命周期钩子&#xff0c;其实webpack也不例外&#xff0c;在使用webpack的时候&#xff0c;我们有时候需要在 webpack 构建流程中引入自定义的行为&#xff0c;这个时候就可以在 hooks 钩子中添加自己的方…