当前位置: 首页 > news >正文

【Android基础回顾】七:内存管理机制

Android 的内存管理机制是一个多层次的复杂系统,旨在高效利用有限的物理内存(RAM),在保证前台应用流畅运行的同时,尽可能在后台保留更多应用以提高启动速度(多任务)。

它的核心机制结合了 Linux 内核的基础功能和 Android 特有的优化策略。

1 基于 Linux 内核的内存管理 (基础层)

1.1 分页与虚拟内存

与所有现代操作系统一样,Android 使用虚拟内存系统。每个进程运行在自己的私有虚拟地址空间中。

内核和 MMU 负责将虚拟地址映射到物理 RAM 或存储上的交换空间(尽管 Android 对传统交换的使用非常谨慎)。

1.2 内存分配

应用通过 malloc、new 等标准库调用请求内存。内核负责分配物理页帧。

1.3 内存不足终止机制

当系统内存严重不足时,Linux 内核的 OOM Killer 会被触发,根据某种策略选择并终止进程以释放内存。

2 Android 特有的优化层 (用户空间)

2.1 LMK(Low Memory Killer)

这个是 Android 对标准 Linux OOM Killer 的关键增强和替代。它更主动和可预测。
下面是LMK的一些机制:

  • 内存压力等级: LMK 定义了一系列不断升高的内存阈值。
  • 进程分类: 每个进程都有一个 oom_adj_score 或 oom_score_adj 值(范围通常从 -1000 到 1000+),数值越大表示优先级越低、越容易被杀。这个值由 ActivityManagerService 根据进程状态动态调整。
  • 按优先级终止: 当可用内存低于某个阈值时,LMK 会查找当前阈值对应的 oom_adj 级别,并终止该级别或更高级别(数值更大,即优先级更低)的进程,直到可用内存回升到安全水平。

下面是一些非系统应用常见的oom_adj级别:

调整级别常量数值范围描述
FOREGROUND_APP_ADJ0前台应用(用户正在交互)。
VISIBLE_APP_ADJ100可见应用(如弹出对话框或小部件)。
PERCEPTIBLE_APP_ADJ200可感知应用(如后台播放音乐)。
BACKUP_APP_ADJ300正在执行备份操作的进程。
HEAVY_WEIGHT_APP_ADJ400重量级后台应用(较少使用)。
SERVICE_ADJ500服务进程(后台服务)。
HOME_APP_ADJ600Home 应用(Launcher)。
PREVIOUS_APP_ADJ700上一个应用(通常优先级略高于纯后台)。
CACHED_APP_MIN_ADJ800-999空进程 / 缓存应用。最先被终止,数值越大越优先被杀。
NATIVE_ADJ1000+系统原生进程(通常不会被杀)。

2.2 应用组件生命周期与内存管理

ActivityManagerService 是核心管理者,负责启动、停止、管理四大组件(Activity, Service, BroadcastReceiver, ContentProvider)的生命周期。

当系统内存不足时,AMS 会首先尝试终止空进程(Cached App。如果还不够,按 oom_adj 优先级从低到高终止包含 Service 或其他组件的后台进程。

最后才会考虑终止可见或前台进程(这是最坏情况)。

2.3 响应内存压力,onTrimMemory() 回调

这是应用响应内存压力的主要方式。系统会根据当前内存压力等级(TRIM_MEMORY_* 常量)调用此方法。

应用应根据等级释放相应资源,下面是几个等级常量:

  • TRIM_MEMORY_RUNNING_MODERATE/CRITICAL: 应用正在前台运行,但系统开始感到压力(CRITICAL 表示可能很快被杀其他进程)。
  • TRIM_MEMORY_UI_HIDDEN: 应用 UI 刚被隐藏(如按 Home 键),是释放仅 UI 使用资源的好时机。
  • TRIM_MEMORY_BACKGROUND/MODERATE/COMPLETE: 应用在后台(LRU 列表位置不同)。COMPLETE 表示进程在列表末尾,可能很快被杀,应尽可能释放资源以争取不被杀或被杀后能快速重建。

正确响应这个回调可以显著降低应用被 LMK 终止的概率。

2.4 垃圾回收(GC)

Android 使用 分代垃圾收集器 ,通常是 ART 运行时中的 Concurrent Mark-Sweep 或其变种。

主要针对 Java/Kotlin 堆内存(对象实例)。

GC 是自动触发的(根据分配速率、堆使用情况等),我们通常不应手动调用 System.gc(),因为 ART 的 GC 策略更智能,手动调用可能打乱其节奏或造成不必要的卡顿。

整体来说,内存泄漏是导致应用内存占用过高甚至 OOM 的主要原因。

2.5 Native 内存管理

native内存还是需要通过 malloc/free、new/delete 手动管理。我们需自行负责分配和释放,否则会导致 Native 内存泄漏。

有个需要注意的点是,Bitmap 像素数据在 Android 8.0 之前分配在 Native 堆(通过 libandroid_runtime.so),之后主要分配在 Java 堆。

2.6 共享内存

Android 的共享内存机制是其高效进程间通信(IPC)和内存管理的核心基础之一,其底层实现结合了 Linux 内核原生机制 和 Android 特有的优化扩展。

2.6.1 基础层:Linux 共享内存机制

Android 基于 Linux 内核,因此继承了 Linux 的共享内存基础能力。
但是,Linux 共享内存的局限性:

缺乏精细的权限控制和生命周期管理。

未针对移动设备的小内存场景优化。

无法与 Android 的 Binder 等机制深度集成。

2.6.2 Android 的核心扩展Ashmem(Anonymous Shared Memory)

Android 在 Linux 基础上引入了 Ashmem,专门为移动场景优化,它的关键特性如下:

  • 匿名共享内存,无需依赖文件系统路径或键值,通过文件描述符(fd)传递共享内存。
  • 基于 mmap() 的零拷贝,进程通过 mmap() 直接映射同一块物理内存,避免数据复制。
  • 动态内存回收(“Unpin” 机制),允许内核在内存不足时回收未被“钉住”(pinned)的内存页(类似交换分区,但更高效)。
  • 精细化访问控制,通过 Binder 传递 fd 时,可附加权限限制(如只读)。

2.6.3 Android 的共享内存高级封装

MemoryFile,他的原理是基于 Ashmem 的 Java 封装,内部通过 JNI 调用 ashmem_create_region()。

使用场景:
适合在 Java 层共享较大数据块(如摄像头帧、传感器数据)。

MemoryFile memoryFile = new MemoryFile("my_shm", size);
memoryFile.getOutputStream().write(data); // 写入数据// 通过 Binder 传递 MemoryFile 的 FileDescriptor
ParcelFileDescriptor pfd = memoryFile.getFileDescriptor();

SharedMemory(Java,API 27+),它替代 MemoryFile,支持更精细的控制(如只读共享)和 AIDL 直接传递。

SharedMemory sharedMem = SharedMemory.create("my_shm", size);
ByteBuffer buffer = sharedMem.mapReadWrite(); // 映射为 ByteBuffer// 通过 Binder 传递 SharedMemory
bundle.putParcelable("shm", sharedMem);

2.6.4 共享内存的生命周期与同步

共享内存的生命周期管理,基于引用计数,通过文件描述符(fd)的传递和关闭控制内存释放。当所有进程关闭 fd 后,内存由内核回收。
Binder 传递 fd,Android 的 Binder 机制支持传递 fd,接收方会获得一个独立的 fd 指向同一块内存。

而关于共享内存的同步机制,本身是没有同步机制的,需要我们自己处理。

Q&A

需要频繁读写的大块内存,同时需要兼顾高效,比如需要实时读取usb摄像头的数据,有什么方案?

共享内存是个不错的选择。

持续更新中。。。

相关文章:

  • Android7 Input(十)View 处理Input事件pipeline
  • 【android bluetooth 协议分析 02】【bluetooth hal 层详解 7】【高通蓝牙hal-读流程介绍】
  • 国产linux系统(银河麒麟,统信uos)使用 PageOffice在线编辑word文件保存数据同时保存文件
  • 第46节:多模态分类(图像+文本)
  • Java在word中指定位置插入图片。
  • 如何在电脑上轻松访问 iPhone 文件
  • LabVIEW自感现象远程实验平台
  • Java编程课(一)
  • 力扣HOT100之二分查找: 34. 在排序数组中查找元素的第一个和最后一个位置
  • Android Test2 获取系统android id
  • DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_天气预报日历示例(CalendarView01_18)
  • WordZero:让Markdown与Word文档自由转换的Golang利器
  • 装备制造项目管理具备什么特征?如何选择适配的项目管理软件系统进行项目管控?
  • 【SSM】SpringBoot笔记2:整合Junit、MyBatis
  • 【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理
  • 2025前端微服务 - 无界 的实战应用
  • 深入浅出 Scrapy:打造高效、强大的 Python 网络爬虫
  • 初探Service服务发现机制
  • QT使用WxSQLite3打开加密数据库并查询
  • Django CMS 的 Demo
  • 中山做网站排名/中国新闻最新消息今天
  • 中小企业网站设计/广东疫情动态人民日报
  • 常见网站建设/广告软文
  • 庆阳网站设计定制/网站排名查询平台
  • 网站标题间隔符/seo营销名词解释
  • 电脑做网站怎么解析域名/长尾词挖掘工具爱站网