【转】Android内存机制分析2——分析APP内存使用情况

摘要:
上一篇文章描述了在dalvik中运行的Android应用程序分配的堆和堆栈内存之间的差异,以及程序中的代码将在何处运行。今天主要是关于如何分析Android中的程序内存使用情况。Android程序内存通常限制在16M,有些是24M。在进行应用程序开发时,您需要了解系统的GC机制是如何工作的。Android使用有向图作为遍历和回收内存的机制。

上面一篇文章说了Android应用运行在dalvik里面分配的堆和栈内存区别,以及程序中什么代码会在哪里运行。今天主要是讲解一下Android里面如何分析我们程序内存使用情况。以便后续可以分析我们程序瓶颈,优化方案。

(PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)

1、APP默认分配内存大小

  在Android里,程序内存被分为2部分:native和dalvik,dalvik就是我们普通的java使用内存,也就是我们上一篇文章分析堆栈的时候使用的内存。我们创建的对象是在这里面分配的,对于内存的限制是 native+dalvik 不能超过最大限制。android程序内存一般限制在16M,也有的是24M(早期的Android系统G1,就是只有16M)。具体看定制系统的设置,在Linux初始化代码里面Init.c,可以查到到默认的内存大小。有兴趣的朋友,可以分析一下虚拟机启动相关代码。这块比较深入,目前我也没时间去分析,后面有空会去钻研一下。

//Edited by mythou //http://www.cnblogs.com/mythou/
gDvm.heapSizeStart = 2 * 1024 * 1024;   // heap初始化大小为2M
gDvm.heapSizeMax = 16 * 1024 * 1024;    // 最大的heap为16M

2、Android的GC如何回收内存

  Android的一个应用程序的内存泄露对别的应用程序影响不大。为了能够使得Android应用程序安全且快速的运行,Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。Android为不同类型的进程分配了不同的内存使用上限,如果程序在运行过程中出现了内存泄漏的而造成应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉,这使得仅仅自己的进程被kill掉,而不会影响其他进程(如果是system_process等系统进程出问题的话,则会引起系统重启)。

  做应用开发的时候,你需要了解系统的GC(垃圾回收)机制是如何运行的,Android里面使用有向图作为遍历回收内存的机制。Java将引用关系考虑为图的有向边,有向边从引用者指向引用对象。线程对象可以作为有向图的起始顶点,该图就是从起始顶点开始的一棵树,根顶点可以到达的对象都是有效对象,GC不会回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。

  因此对于我们已经不需要使用的对象,我们可以把它设置为null,这样当GC运行的时候,就好遍历到你这个对象已经没有引用,会自动把该对象占用的内存回收。我们没法像C++那样马上释放不需要的内存,但是我们可以主动告诉系统,哪些内存可以回收了。

3、查看应用内存使用情况

  下面我们看看如何在开发过程中查看我们程序运行时内存使用情况。我们可以通过ADB的一个命令查看:

//Edited by mythou //http://www.cnblogs.com/mythou/
//$package_name:应用包名
//$pid:应用进程ID,可以用PS命令查看
adb shell dumpsys meminfo $package_name or $pid

【转】Android内存机制分析2——分析APP内存使用情况第1张

  上面是我使用包名查看Gallery例子的内存使用情况图,里面信息很多,不过我们主要关注的是native和Davilk的使用情况。(Android2.X和Android4.X查看的信息排序是不一样的,内容差不多,不过排布有差异,我上面是4.0的截图)

  Android底层内核是基于Linux的,而Linux里面相对Window来说,有一点很特别的是,会尽量使用系统内存加载一些缓存数据或者进程间共享数据。Linux本着不用白不用的原则,会尽量使用系统内存,加快我们应用的运行速度。当然,如果我们期待某个需要大内存的应用,系统也能马上释放出一定的内存使用,这是系统内部调度实现。因此严格来说,我们要准备计算Linux下某个进程内存大小比较困难。 因为有paging out to disk(换页),所以如果你把所有映射到进程的内存相加,它可能大于你的内存的实际物理大小。

  • dalvik:是指dalvik所使用的内存。
  • native:是被native堆使用的内存。应该指使用CC++在堆上分配的内存。
  • other:是指除dalvik和native使用的内存。但是具体是指什么呢?至少包括在CC++分配的非堆内存,比如分配在栈上的内存。puzlle!
  • Pss:它是把共享内存根据一定比例分摊到共享它的各个进程来计算所得到进程使用内存。网上又说是比例分配共享库占用的内存,也就是上面所说的进程共享问题。
  • PrivateDirty:它是指非共享的,又不能换页出去(can not be paged to disk )的内存的大小。比如Linux为了提高分配内存速度而缓冲的小对象,即使你的进程结束,该内存也不会释放掉,它只是又重新回到缓冲中而已。
  • SharedDirty:参照PrivateDirty我认为它应该是指共享的,又不能换页出去(can not be paged to disk )的内存的大小。比如Linux为了提高分配内存速度而缓冲的小对象,即使所有共享它的进程结束,该内存也不会释放掉,它只是又重新回到缓冲中而已。

  上面针对meminfo里面的信息给出解析,这些很多我是参考了网上一些文章,所以如果有理解不到位的,欢迎各位指出。

4、程序中获取内存信息

通过ActivityManager获取相关信息,下面是一个例子代码:

复制代码
//Edited by mythou //http://www.cnblogs.com/mythou/
private void displayBriefMemory()  {    
    final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);    
    ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();   
    activityManager.getMemoryInfo(info);    
 
    Log.i(tag,"系统剩余内存:"+(info.availMem >> 10)+"k");   
    Log.i(tag,"系统是否处于低内存运行:"+info.lowMemory);
    Log.i(tag,"当系统剩余内存低于"+info.threshold+"时就看成低内存运行");
}
复制代码

另外通过Debug的getMemoryInfo(Debug.MemoryInfo memoryInfo)可以得到更加详细的信息。跟我们在ADB Shell看到的信息一样比较详细。

5、总结

  今天主要是分析了如何获取我们应用的内存使用情况信息,关于这方面的信息,其实还有其他一些方法。另外还介绍APP应用的默认内存已经Android的GC回收,不过上面只是很浅薄地分析了一下,让大家有个印象。这些东西真要深入分析得花不少精力。因为我们的目的只是解决OOM问题,所以目前没打算深入分析,后面有时间进行Android系统分析的时候,我们再深入分析。下一次我们用以前写的Gallery例子讲解如何避免OOM问题,以及内存优化方法。

  本文转自:http://www.cnblogs.com/mythou/p/3203536.html

免责声明:文章转载自《【转】Android内存机制分析2——分析APP内存使用情况》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ios webview 加载含有中文的URL网页显示白屏BAT教程 :第一节(批处理基础)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux服务器性能查看分析调优

一 linux服务器性能查看 1.1 cpu性能查看 1、查看物理cpu个数: cat /proc/cpuinfo |grep "physical id"|sort|uniq|wc -l 2、查看每个物理cpu中的core个数: cat /proc/cpuinfo |grep "cpu cores"|wc -l 3、逻辑cpu的个数: cat /proc...

MSSQLSERVER 服务运行内存设置较小导致启动服务失败

问题产生原因: 手动设置MSSQLSERVER 运行内存,设置值未达到MSSQLSERVER 服务运行内存最低值(max server memory 所允许的最小内存量是 128 MB。),导致MSSQLSERVER 服务启动失败; 处理方法: 根据网上资料获知,可从DOS界面启动MSSQLSERVER精简版服务,配置MSSQLSERVER服务运行值大小...

DPDK 网络加速在 NFV 中的应用

目录 文章目录 目录 前文列表 传统内核协议栈的数据转发性能瓶颈是什么? DPDK DPDK 基本技术 DPDK 架构 DPDK 核心组件 应用 NUMA 亲和性技术减少跨 NUMA 内存访问 应用 CPU 绑核技术减少上下文切换损耗 应用大页内存技术减少 TLB miss 应用 PMD 轮询技术减少网卡外设的硬件中断 应用 UIO 和内存池技术减...

linux概念之内存分析

linux内存总结 分析样本[root@221-comecs ~]# free total used freeshared buffers cached Mem: 1019820 782912 236908 0 54104 60...

Android 如何优化APP内存

极力推荐Android 开发大总结文章:欢迎收藏程序员Android 力荐 ,Android 开发者需要的必备技能 随机存取存储器(RAM)在任何软件开发环境中都是非常有价值的资源,但对于物理内存经常受到限制的移动操作系统来说,它更有价值。 尽管Android运行时(ART)和Dalvik虚拟机都执行常规垃圾收集,但这并不意味着您可以忽略应用程序分...

什么是内存(二):虚拟内存

通过上一篇文章的扯淡,我们应该已经明白了存储器的层次结构,技术细节很复杂,但是思想却不难理解,因为就是很简单的缓存思想。那么本文我们开始讨论关于内存的另一个话题.虚拟内存。其实思想也是很容易理解的。 我不知道有多少人听过虚拟内存这个概念,但是虚拟内存是计算机系统最重要的概念之一,并且它成功的主要原因就是它一直在沉默的,自动的工作,换句话说,我们这些做应用的...