Android内存

大家好,技术学习最好的一手资源就是英文文档,所以给自己定下一个目标:通过参阅英文技术文档来进一步提高自己的技术能力。下面是我翻译的一篇技术文档,欢迎朋友们拍砖、交流、一起进步。

原文:https://google-developer-training.github.io/android-developer-advanced-course-concepts/unit-2-make-your-apps-fast-and-small/lesson-4-performance/4-2-c-memory/4-2-c-memory.html

内容:

  1. Android内存
  2. 垃圾回收
  3. 内存泄漏和内存抖动
  4. 内存分析工具
  5. 相关实践
  6. 学习更多

Android系统自身会为你管理内存,但如果你的代码没有有效的使用内存,所有的Android管理都不能使你的应用运行良好。清理内存资源需要时间,这会占用其他进程的珍贵毫秒时间。

内存是一个巨大的主题。教你一般的基础知识以及深入的知识,超出了本章的范围。本章提供了Android相关的背景,介绍了在实践中的应用工具及描述了应用中常见的内存相关的问题。

Android内存

Android是一个自身管理内存的环境。你不需要手动管理内存,因为系统已经替你做了。Android团队做了大量的工作尽可能让内存管理更加快速和高效。

Android运行时(5.0)和Dalvik虚拟机使用分页和内存映射来管理内存。当一个app通过分配新对象或者触摸内存映射分页来修改内存时,该内存依然保留在RAM中并不能换出。从一个APP释放内存的唯一方法是释放APP持有的对象引用,来让该内存可被垃圾回收器回收。

学习更多有关ART和Dalvik虚拟机知识。复习java中的内存管理知识。

垃圾回收

清理和释放内存资源的过程被称为垃圾回收。

自动管理内存环境(ART和Davlik虚拟机)会追踪每个内存分配的踪迹。当系统决定一个内存片不再被程序使用时,会将这块内存释放回堆中,而不需要你的干预。垃圾回收有两个目标:

  1. 找到不再被引用和将来不会被访问的数据对象。
  2. 回收这些对象使用的资源。

垃圾回收是一个必须的过程,但如果发生的太频繁,会严重影响APP的性能。即使垃圾回收可以非常快,依然可以影响APP的性能。你一般不通过代码来控制垃圾回收何时发生。

系统有决定何时发生垃圾回收的标准。一旦这个标准被满足,系统开始垃圾回收。如果垃圾回收发生在一个密集处理循环的中间,像动画和音乐播放,它会增加程序处理时间。而这会增加代码执行时间超过16毫秒阈值,以达到高效和流程的帧渲染。

你的代码流可能会使垃圾事件比平常更频繁的发生或者是它们比平常持续的时间更长。例如,如果你在alpha动画中每一帧在内层循环中分配多个对象,你可能会用很多对象污染内存堆。在这种情况下,拉回回收会执行多次回收事件,并会降低你APP的性能。

为了维护一个功能性的多任务环境,Android对堆大小设置了硬性限制(每个应用程序可用的内存)。确切的堆大小根据设备总体RAM多少而变化。如果你的APP已经达到堆容量大小并尝试分配更多内存,它会接收到内存异常(OutOfMemoryError)对象。

Android尝试跨进程共享RAM。具体操作请参考共享内存。要了解如何确定你的应用内存使用,请参见调查你的RAM内存使用。

切换APP

前台APP对用户来讲是可见的或者运行了一个前台服务,例如音乐播放器。当用户切换应用程序,Android系统把不在前台的应用程序保存在“最近最少使用”(LRU)缓存中。例如,当一个APP首次启动时,会为该应用程序创建一个进程,但是当用户离开该APP时,该进程没有退出。系统把该进程保存到缓存中。如果用户返回该APP,系统重新使用该进程,这使的APP切换更快速。

如果你的APP有一个缓存的进程,它保留了当前并不需要的内存,然后你的APP-即使用户没有在使用它,也会影响系统的整体性能。系统一旦内存不足,会杀死缓存中的进程,从最近不常用的进程开始。系统还会考虑占用内存最多的进程,并会暂停他们来释放RAM。

有关更过信息,请参阅进程和线程指南。

内存泄漏和内存抖动

内存泄漏:当你的代码给对象分配内存,但从没有释放该内存就会发生内存泄漏。随着时间的推移,为那些对象分配的内存就像越来越大、不可移动的块,迫使应用程序的剩余部分在剩下的堆空间操作。最终这个程序会耗尽内存并奔溃。内存泄漏是巨大和明显的,比如当你的应用程序加载图片大于可使用内存时。同时内存泄漏也可以是微小并很难发现,因为用户可能只注意到应用程序随着时间的推移变得越来越慢。内存泄漏的最终结果是当用户用尽了可用内存后,从用户角度来看,正常运行了很长一段时间后突然奔溃了。

内存抖动:如果-在短时间内分配和释放了大量对象,使堆饱和,并因此开始更多的垃圾回收,也会使内存变得吃紧。例如,如果在嵌套循环中间或在onDraw()方法中分配新对象就会发生内存抖动。即使应用程序没有用尽内存,用户也会注意到由于频繁的垃圾回收应用程序变慢或变卡。

避免内存泄漏和抖动:

        不要泄漏视图对象

  1. 不要从UI线程外部引用视图对象。如果一个视图没有被使用但依然被引用,那么这个视图和它的整个子层次都不能被释放。视图有对activity的引用,所以视图不能被释放,整个相关的activity依然会停留在内存中。因为用户更改设备方向activity会被重新创建,大量长期不被使用的对象停留在内存中。
  2. 不要在异步回调中引用视图。直到该任务结束视图才可以被释放且在该任务完成的时候,该视图可能已经无效。
  3. 不从静态对象引用视图。静态对象在进程的整个生命周期都存在,远比activity存活时间长。
  4. 不要将视图放入没有明确内存模式的集合中,像WeakHashMap。
  5. 了解更多信息,请观看“不要泄漏视图”视频。
  6. 避免循环分配。不要在内部循环中分配对象。在循环之外进行,或者重新设计以避免分配。
  7. 避免在自定义view的onDraw()方法中分配对象。OnDraw()方法在每一帧中都会被调用。
  8. 使用对象池。分配一组对象并重用它们。对象池是为你保存未使用对象的数据结构。当你使用完对象,不是释放回堆,而是将对象移交给对象池。以后,当某个函数该类型的对象时,可以从对象池中获取,而不是从堆中分配新的。Android提供了Pool类。然而,如果你使用pool类,你必须为这些对象管理自己的内存。同过“对象池视频”了解更多。

为了了解更多,请观看“内存泄漏的性能成本和内存抖动及性能视频”。

内存分析工具

内存分析器是Android分析器的一个组件。通过内存分析器你可以

  1. 在时间轴上查看已分配对象和垃圾回收事件的实时数量
  2. 获取堆存储
  3. 记录内存分配

启动内存分析器(看下图)

  1. 在一个已开启了开发者选项的设备上运行你的APP。
  2. 在Android studio中,从底部工具栏打开android Profiler(1)
  3. 选择你的设备和应用程序,如果它们还没被选择(2)。内存图形开始显示(3)。

当你第一次打开内存分析器,时间轴显示应用程序使用的总内存数量。内存大小在Y轴上显示。

单击内存条,图像会展开进入内存专题页面。每中内存类型(例如java,native,graphics)在堆叠的内存图形中以不同的颜色进行显示。上图中的图例显示了每种内存的数量。

下面的图和解释总结了内存分析器中可用的工具和功能。有关如何使用该工具的详细信息,请参考Memory Profilerr文档和Memory Profiler实用手册。

图像说明:

  1. 强制垃圾回收。
  2. 捕获堆转储。
  3. 记录内存分配。
  4. 记录内存分配的时间段。
  5. 在时间轴中指示时间内的内存分配结果。在查看堆转储或内存分配时,你可以从这个列表中选择一个类名来查看右侧的实例列表。
  6. 单击类名来填充实例视图。
  7. 单击一个实例来显示它的调用栈。当你查看分配记录时,这堆栈调用将会为分配的内存位置显示堆栈调用记录。当你查看堆转储时,调用堆栈将会显示该对象的其余引用。

要导出记录到hprof文件或alloc文件,请单击左上角的堆转储和分配窗口的导出按钮。稍后将该文件加载到android studio以查看。有关用户界面的详细信息和使用hprof文件的更多详细信息,请参阅hprof文档。

相关实践

相关的练习和实战文档再内存分析器中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值