转载自:http://blog.csdn.net/anlegor/article/details/23398785

Android内存管理机制:

Android内存管理主要有:LowMemory Killer机制,Ashmem,PMEM/ION及Native内存和Dalvik内存管理管理和JVM垃圾回收机制。

LowMemory Killer机制:

源码位置drivers/staging/Android/lowmemorykiller.c

Android是一个多任务系统,也就是说可以同时运行多个程序,这个大家应该很熟悉。一般来说,启动运行一个程序是有一定的时间开销的,因此为了加快运行速度,当你退出一个程序时,Android并不会立即杀掉它,这样下次再运行该程序时,可以很快的启动。随着系统中保留的程序越来越多,内存肯定会出现不足,low memory killer就是在系统内存低于某值时,清除相关的程序,保障系统保持拥有一定数量的空闲内存。

Low memorykiller根据两个原则,进程的重要性和释放这个进程可获取的空闲内存数量,来决定释放的进程。

进程的重要性,由task_struct->signal_struct->oom_adj决定,

Android将程序的重要性分成以下几类,按照重要性依次降低的顺序,每个程序都会有一个oom_adj值,这个值越小,程序越重要,被杀的可能性越低:

除了上述程序重要性分类之外,Android系统还维护着另外一张表minfree用于维护内存警戒值,这两张表构成一个对应关系,两张表在” /sys/module/lowmemorykiller/parameters/”下保存。

adj文件内容如下形如”0,1,2,4,9,15”,minfree文件内容形如”8192,10240,12288,14336,1638,20480”,这样形成的表结构如下:

例如,当系统可用内存小于12384*4K大小时,会开始杀掉oom_adj>=9级别的进程。

进程的内存,通过get_mm_rss获取,在相同的oom_adj下,内存大的,优先被杀。

Ashmem(匿名内存共享):

源码位置:kernel/mm/ashmem.c

为进程间提供提供大块共享内存,同时为内核提供回收和管理这个内存的机制。

相比于malloc和anonymous/namedmmap等传统的内存分配机制,其优势是通过内核驱动提供了辅助内核的内存回收算法机制(pin/unpin)。什么是pin和unpin呢?具体来讲,就是当你使用Ashmem分配了一块内存,但是其中某些部分却不会被使用时,那么就可以将这块内存unpin掉。

unpin后,内核可以将它对应的物理页面回收,以作他用。你也不用担心进程无法对unpin掉的内存进行再次访问,因为回收后的内存还可以再次被获得(通过缺页handler),因为unpin操作并不会改变已经 mmap的地址空间。

AndroidPMEM/ION内存管理器:

源码位置:drivers/misc/pmem.c

AndroidPmem是为了实现共享大尺寸连续物理内存而开发的一种机制,该机制对dsp,gpu等部件非常有用。Pmem相当于把系统内存划分出一部分单独管理,即不被linux mm管理,实际上linux mm根本看不到这段内存。

Pmem和Ashmem都通过mmap来实现共享内存,其区别在于Pmem的共享区域是一段连续的物理内存,而Ashmem的共享区域在虚拟空间是连续的,物理内存却不一定连续。dsp和某些设备只能工作在连续的物理内存上,这样cpu与dsp之间的通信就需要通过Pmem来实现。

ION是google在Android4.0ICS为了解决内存碎片管理而引入的通用内存管理器,它会更加融合kernel。目前QCOM MSM, NVDIA Tegra, TI OMAP, MRVL PXA都用ION替换PMEM。

ION 定义了四种不同的heap,实现不同的内存分配策略。

AndroidNative内存和Dalvik内存管理:

Native进程是采用C/C++实现,不包含dalvik实例的进程,/system/bin/目录下面的程序文件运行后都是以native进程形式存在的,如/system/bin/surfaceflinger、/system/bin/rild、procrank等就是native进程,地址空间结构如下:

java进程是Android中运行于dalvik虚拟机之上的进程。dalvik虚拟机的宿主进程由fork()系统调用创建,所以每一个java进程都是存在于一个native进程中,因此,java进程的内存分配比native进程复杂,因为进程中存在一个虚拟机实例。Android系统中的应用程序基本都是java进程,如桌面、电话、联系人、状态栏等等,进程结构如下:

Stack空间(进栈和出栈)由操作系统控制,其中主要存储函数地址、函数参数、局部变量等等,所以Stack空间不需要很大,一般为几MB大小。

Heap空间的使用由程序员控制,程序员可以使用malloc、new、free、delete等函数调用来操作这片地址空间。Heap为程序完成各种复杂任务提供内存空间,所以空间比较大,一般为几百MB到几GB。正是因为Heap空间由程序员管理,所以容易出现使用不当导致严重问题。

进程空间中的heap空间是我们需要重点关注的。heap空间完全由程序员控制,我们使用的malloc、C++ new和java new所申请的空间都是heap空间, C/C++申请的内存空间在native heap中,而java申请的内存空间则在dalvik heap中。

进程的内存空间只是虚拟内存(或者叫作逻辑内存),而程序的运行需要的是实实在在的内存,即物理内存(RAM)。在必要时,操作系统会将程序运行中申请的内存(虚拟内存)映射到RAM,让进程能够使用物理内存。

RAM作为进程运行不可或缺的资源,对系统性能和稳定性有着决定性影响。另外,RAM的一部分被操作系统留作他用,比如显存等等,内存映射和显存等都是由操作系统控制,我们也不必过多地关注它,进程所操作的空间都是虚拟地址空间,无法直接操作RAM。示意图如下:

Android系统对dalvik的vm heapsize作了硬性限制,当java进程申请的java空间超过阈值时,就会抛出OOM异常,在/system/build.prop中有三项可以配置相关信息。

dalvik.vm.heapstartsize:堆分配的初始大小,调整这个值会影响到应用的流畅性和整体ram消耗。这个值越小,系统ram消耗越慢,但是由于初始值较小,一些较大的应用需要扩张这个堆,从而引发gc和堆调整的策略,会应用反应更慢。相反,这个值越大系统ram消耗越快,但是程序更流畅。

dalvik.vm.heapgrowthlimit:受控情况下的极限堆(仅仅针对dalvik堆,不包括native堆)大小,dvm heap是可增长的,但是正常情况下dvm heap的大小是不会超过dalvik.vm.heapgrowthlimit的值(非正常情况下面会详细说明)。这个值控制那些受控应用的极限堆大小,如果受控的应用dvm heap size超过该值,则将引发oom(out of memory)。

dalvik.vm.heapsize:不受控情况下的极限堆大小,这个就是堆的最大值。不管它是不是受控的。这个值会影响非受控应用的dalvikheap size。一旦dalvik heap size超过这个值,直接引发oom。

JVM垃圾回收机制:

JVM的垃圾原理是这样的,它把对象分为年轻代(Young)、年老代(Tenured)、持久代(Perm),对不同生命周期的对象使用不同的垃圾回收算法。

年轻代(Young):年轻代分为三个区,一个eden区,两个Survivor区。程序中生成的大部分新的对象都在Eden区中,当Eden区满时,还存活的对象将被复制到其中一个Survivor区,当此Survivor区的对象占用空间满了时,此区存活的对象又被复制到另外一个Survivor区,当这个Survivor区也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制到年老代。

年老代(Tenured)年老代存放的是上面年轻代复制过来的对象,也就是在年轻代中还存活的对象,并且区满了复制过来的。一般来说,年老代中的对象生命周期都比较长。

持久代(Perm)用于存放静态的类和方法,持久代对垃圾回收没有显著的影响。

Android内存分析工具:

         内存监控工具DDMS:

Ddms可以在eclipse中安装对应的插件,同时在androidsdk的tools文件夹也有同样的工具,并且功能比eclipse插件更完备。

切换到eclipse的ddms视图后,从设备中选择要监控的进程(手机需要开启usb调试,被监控应用的manifest中android:debuggable应该为true)

如下图操作,我们主要关注dataobject类型的total size数据在使用过程中是否出现异常的数据波动。

Eclipse MAT插件:

Mat是eclipse的一个插件,安装完成之后,在ddms试图下,同时在左侧设备试图上方选择“Update Heap”和“Dump HPROF file”按钮,在弹出的窗口中选择“Leak Suspects Report”并finish,即可出现下面的结果试图:

进入leaksuspects之后,就能列出所有可能有泄漏的地方以及代码片段

Adb shell的dumpsys meminfo命令:

Adbshell的cat命令:

应用内存分配跟踪工具Allocation tracker:

同样该功能用到ddms ,只是里面提供的一个子功能而已,能够知道所有对象的分配是在代码的哪个类,哪个文件的哪一行。

AndroidOOM的常见原因:

非静态内部类的静态实例容易造成内存泄漏

activity使用静态成员

使用handler时的内存问题

注册某个对象后未反注册

集合中对象没清理造成的内存泄露

资源对象没关闭造成的内存泄露

一些不良代码成内存压力:Bitmap使用不当;构造Adapter时,没有使用缓存的 convertView;在经常调用的方法中创建对象(例如循环)

参考资料:

Androidmemory fundamentals

http://www.slideshare.net/tarasleskiv/android-memory-fundamentals?qid=c8462372-7470-4459-a76c-552c678724c0&v=qf1&b=&from_search=2

Forensic Memory Analysis of Android'sDalvik Virtual Machine

http://www.slideshare.net/SOURCEConference/forensic-memory-analysis-of-androids-dalvik-virtual-machine?qid=c8462372-7470-4459-a76c-552c678724c0&v=qf1&b=&from_search=6

Memory management for_android_apps

http://www.slideshare.net/shaobin0604/memory-management-forandroidapps?qid=c8462372-7470-4459-a76c-552c678724c0&v=qf1&b=&from_search=11

android内存管理机制分析

http://www.doc88.com/p-992213371842.html

Android 操作系统的内存回收机制

http://blog.jobbole.com/25169/

Android系统匿名共享内存(AnonymousShared Memory)C++调用接口分析

http://blog.csdn.net/luoshengyang/article/details/6939890

Android系统匿名共享内存Ashmem(AnonymousShared Memory)简要介绍和学习计划 - 老罗的Android之旅 - 博客频道 - CSDN.NET

http://blog.csdn.net/luoshengyang/article/details/6651971

程序源代码分析 - 老罗的Android之旅 - 博客频道 - CSDN.NET

http://blog.csdn.net/luoshengyang/article/details/6664554

Android系统匿名共享内存Ashmem(AnonymousShared Memory)在进程间共享的原理分析 - 老罗的Android之旅 - 博客频道 - CSDN.NET

http://blog.csdn.net/luoshengyang/article/details/6666491

Windows内存与进程管理器底层分析

http://www.cnblogs.com/zudn/archive/2010/12/29/1920593.html

什么是内存直接映像技术?它有何特点?

http://zhidao.baidu.com/link?url=e8NFxuOaY9UsOxKGklWmTR20-gpDGy48eE1SerGNCjAYbg3Xj-Fp0pqBSAKFy_AEjyKQOWmx3QHGn4ldWgec0M1wxBowDOT59Bua2O0DjZC

Mysteries of Windows Memory ManagementRevealed

http://media.ch9.ms/teched/na/2011/ppt/WCL406.pptx

全面介绍Windows内存管理机制及C++内存分配实例

http://blog.csdn.net/yeming81/article/details/2046193

技术内幕:Android对Linux内核的增强

http://tech.it168.com/a2011/0805/1228/000001228471_all.shtml

android内存管理了解_百度文库

http://wenku.baidu.com/link?url=bGaPQbl7u1_JmKSJ5nVBv1dHtvGSXREyv_7PeSt9_FCx20I5oK1EaEgno9d6Ked4Kao92yoP_7X6gOQToylezMwEn-inKnBxb7SAoJ3jH6m

Android low memory killer 详解-tuyer-ChinaUnix博客

http://blog.chinaunix.net/uid-20321537-id-3228776.html

Linux 设备文件简介

http://www.jinbuguo.com/kernel/device_files.html

Explore Android Internals

http://www.slideshare.net/jserv/android-internals-30176596?qid=a3be858d-e483-423c-be0e-a85e0a08fdd6&v=qf1&b=&from_search=4

Inside Android's Dalvik VM - NEJUG Nov 2011

http://www.slideshare.net/dougqh/inside-androids-dalvik-vm-nejug-nov-2011?qid=a3be858d-e483-423c-be0e-a85e0a08fdd6&v=qf1&b=&from_search=3

android之ION内存管理器(1)-- 简介

http://blog.csdn.net/crazyjiang/article/details/7927260

Android进程的内存管理分析

http://blog.csdn.net/gemmem/article/details/8920039

Gc in android

http://www.slideshare.net/VikasBalikai/gc-in-android

Android内存泄漏分析及调试

http://blog.csdn.net/gemmem/article/details/13017999

Android OOM介绍及分析方法

http://blog.csdn.net/gemmem/article/details/8964397

[Android Memory] Android内存管理、监测剖析的更多相关文章

  1. Android应用的内存管理

    管理应用的内存可以分为两个部分内容: 1. 首先需要理解:How Android Manages App Processes and Memory Allocation? 2. 其次需要考虑:我们设计 ...

  2. Android中的内存管理机制以及正确的使用方式

    概述 从操作系统的角度来说,内存就是一块数据存储区域,属于可被操作系统调度的资源.现代多任务(进程)的操作系统中,内存管理尤为重要,操作系统需要为每一个进程合理的分配内存资源,所以可以从两方面来理解操 ...

  3. Objective-C Memory Management 内存管理 2

    Objective-C Memory Management 内存管理  2  2.1 The Rules of Cocoa Memory Management 内存管理规则 (1)When you c ...

  4. Objective -C Memory Management 内存管理 第一部分

    Objective -C Memory Management  内存管理  第一部分 Memory management is part of a more general problem in pr ...

  5. 【转】Android中的内存管理--不错不错,避免使用枚举类型

    原文网址:http://android-performance.com/android/2014/02/17/android-manage-memory.html 本文内容翻译自:http://dev ...

  6. Android进程的内存管理分析

    尊重原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/8920039 最近在网上看了不少Android内存管理方面的博文,但是文章大多 ...

  7. android的低内存管理器【转】

    本文转载自:http://blog.csdn.net/haitaoliang/article/details/22092321 版权声明:本文为博主原创文章,未经博主允许不得转载. 安卓应用不用太在意 ...

  8. Android进阶篇-内存管理

    很多时候我们需要考虑Android平台上的内存管理问题,Dalvik VM给每个进程都分配了一定量的可用堆内存,当我们处理一些耗费资源的操作时可能会产生OOM错误(OutOfMemoryError)这 ...

  9. Linux内核之内存管理完全剖析

    linux虚拟内存管理功能 ? 大地址空间:? 进程保护:? 内存映射:? 公平的物理内存分配:? 共享虚拟内存.实现结构剖析   (1)内存映射模块(mmap):负责把磁盘文件的逻辑地址映射到虚拟地 ...

随机推荐

  1. 51nod 1254 最大子段和 V2 ——单调栈

    N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  2. certbot 免费httos证书申请

    https://keelii.com/2016/06/12/free-https-cert-lets-encrypt-apply-install/

  3. Python爬虫学习 - day1 - 爬取图片

    利用Python完成简单的图片爬取 最近学习到了爬虫,瞬时觉得很高大上,想取什么就取什么,感觉要上天.这里分享一个简单的爬取汽车之家文章列表的图片教程,供大家学习. 需要的知识点储备 本次爬虫脚本依赖 ...

  4. linux中的阻塞机制及等待队列【转】

    转自:http://www.cnblogs.com/gdk-0078/p/5172941.html 阻塞与非阻塞是设备访问的两种方式.驱动程序需要提供阻塞(等待队列,中断)和非阻塞方式(轮询,异步通知 ...

  5. ARM 处理器架构【转】

    ARM 处理器架构 转自:http://www.arm.com/zh/products/processors/instruction-set-architectures/index.php ARM 架 ...

  6. phoronix-test-suite测试云服务器

    centos系统 phoronix-test-suite是目前Linux下比较常用的性能测试软件. 使用phoronix-test-suite条件前提:需要安装php5,需要PHP都DOM扩展 因为是 ...

  7. 《Java编程思想》笔记 第十一章 持有对象

    1.保存对象引用 1.数组,数组具有固定大小 2.容器类,可自动调节大小 2.容器类 List  Set  Queue  Map 及常用的实现类 2.1 Collection (接口) 保存独立的元素 ...

  8. k8s的故障切换(failover)

    当前3个节点的状态都为ready 当前node1有两个pod  node2有1个pod 现在将node1关机会有怎样的现象 ping 分布在node1节点的pod地址已经ping不通. 在node1节 ...

  9. poj 2007(凸包)

    Scrambled Polygon Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 8005   Accepted: 3798 ...

  10. ES6的特性(译+注解)

    介绍 ES6,也叫ECMAScript2015(以下统称ES6),是ECMAScript标准的最新版本.这个标准在2015年6月份被正式批准.ES6是js语言很有意义的一次更新,也是2009年ES5被 ...