[Android Memory] Android内存管理、监测剖析

简介:

转载自: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
本文转自demoblog博客园博客,原文链接http://www.cnblogs.com/0616--ataozhijia/p/4136360.html如需转载请自行联系原作者

demoblog
相关文章
|
24天前
|
编解码 算法 Java
构建高效的Android应用:内存优化策略详解
随着智能手机在日常生活和工作中的普及,用户对移动应用的性能要求越来越高。特别是对于Android开发者来说,理解并实践内存优化是提升应用程序性能的关键步骤。本文将深入探讨针对Android平台的内存管理机制,并提供一系列实用的内存优化技巧,以帮助开发者减少内存消耗,避免常见的内存泄漏问题,并确保应用的流畅运行。
|
25天前
|
缓存 移动开发 Java
构建高效Android应用:内存优化实战指南
在移动开发领域,性能优化是提升用户体验的关键因素之一。特别是对于Android应用而言,由于设备和版本的多样性,内存管理成为开发者面临的一大挑战。本文将深入探讨Android内存优化的策略和技术,包括内存泄漏的诊断与解决、合理的数据结构选择、以及有效的资源释放机制。通过实际案例分析,我们旨在为开发者提供一套实用的内存优化工具和方法,以构建更加流畅和高效的Android应用。
|
28天前
|
监控 Java Android开发
构建高效Android应用:从内存管理到性能优化
【2月更文挑战第30天】 在移动开发领域,打造一个流畅且响应迅速的Android应用是每个开发者追求的目标。本文将深入探讨如何通过有效的内存管理和细致的性能调优来提升应用效率。我们将从分析内存泄露的根本原因出发,讨论垃圾回收机制,并探索多种内存优化策略。接着,文中将介绍多线程编程的最佳实践和UI渲染的关键技巧。最后,我们将通过一系列实用的性能测试工具和方法,帮助开发者监控、定位并解决性能瓶颈。这些技术的综合运用,将指导读者构建出更快速、更稳定、用户体验更佳的Android应用。
|
1月前
|
传感器 缓存 Android开发
构建高效的Android应用:从内存优化到电池寿命
【2月更文挑战第23天】在移动开发领域,性能优化是一个持续的挑战。特别是对于Android应用来说,由于设备多样性和碎片化问题,开发者需要采取一系列策略来保证应用的流畅运行。本文深入探讨了Android应用的性能优化,包括内存管理、电池使用效率和UI渲染。我们将提供实用的技巧和最佳实践,帮助开发者构建更加高效、响应迅速的应用,从而改善用户体验并延长设备电池寿命。
13 1
|
1月前
|
监控 Java Android开发
构建高效Android应用:从内存优化到电池寿命
【2月更文挑战第18天】在移动设备的生态系统中,资源管理是确保用户满意度的关键。特别是对于Android开发者来说,优化应用的内存使用和延长电池寿命是提升用户体验的重要方面。本文将深入探讨Android平台上的内存管理机制,提供实用的代码级优化技巧,并讨论如何通过调整应用行为来减少能量消耗,最终目标是为开发者提供一套全面的技术策略,以打造更加高效、响应迅速且电池友好的Android应用。
29 5
|
2月前
|
测试技术 Android开发 UED
如何对APP的内存使用情况进行监测?
如何对APP的内存使用情况进行监测?
|
3月前
|
Java 数据库连接 程序员
Android 性能优化: 什么是内存泄漏?如何在Android中避免内存泄漏?
Android 性能优化: 什么是内存泄漏?如何在Android中避免内存泄漏?
65 2
|
5月前
|
Android开发
[√]Android 通过adb内存监测方法
[√]Android 通过adb内存监测方法
121 1
|
5月前
|
缓存 Android开发 C++
[√]Android平台ParticleSystem内存泄露的排查过程
[√]Android平台ParticleSystem内存泄露的排查过程
34 1
|
算法 Java Android开发