全部内容均来源于官方文档https://developer.android.com/training/articles/memory.html

only way to completely release memory from your app is to release object references you may be holding, making the memory available to the garbage collector.

从应用全然释放内存的唯一方式就是释放你所引用的的对象,使其对GC可见。


How Android Manages Memory

Android系统怎样管理内存

1、Sharing Memory

共享内存

In order to fit everything it needs in RAM, Android tries to share RAM pages across processes. It can do so in the following ways:

为了适应内存所需,Android会跨进程共享内存页面。通过下列方式:

1)Each app process is forked from an existing process called Zygote.

每一个应用进程从一个叫做Zygote的已有进程fork来

2)Most static data is mmapped into a process.

大部分静态数据被映射在一个进程

3)In many places, Android shares the same dynamic RAM across processes using explicitly allocated shared memory regions (either with ashmem or gralloc).

非常多场合。Android使用指定的分配内存区域来跨进程共享同样的动态内存。


2、Allocating and Reclaiming App Memory

分配和回收内存

Here are some facts about how Android allocates then reclaims memory from your app:

下面是一些系统回收和分配内存的策略:

1)The Dalvik heap for each process is constrained to a single virtual memory range.

每一个进程的Dalvik heap被限定在一个内存区间。

2)The logical size of the heap is not the same as the amount of physical memory used by the heap.

堆内存的逻辑大小和物理大小不同样

3)The Dalvik heap does not compact the logical size of the heap, meaning that Android does not defragment the heap to close up space. Android can only shrink the logical heap size when there is unused space at the end of the heap.

Dalvik heap不会为了使内存连续而整理内存碎片


3、Restricting App Memory

限制应用内存

To maintain a functional multi-tasking environment, Android sets a hard limit on the heap size for each app. The exact heap size limit varies between devices based on how much RAM the device has available overall. If your app has reached the heap capacity and tries to allocate more memory, it will receive an OutOfMemoryError.

为了维持一个多任务环境,系统严格限制每一个应用的堆内存大小,而且随不同设备有所不同。超出这个容量就会造成OOM。


4、Switching Apps

应用切换

Instead of using swap space when the user switches between apps, Android keeps processes that are not hosting a foreground (“user visible”) app component in a least-recently used (LRU) cache. For example, when the user first launches an app, a process is created for it, but when the user leaves the app, that process does not quit. The system keeps the process cached, so if the user later returns to the app, the process is reused for faster app switching.

系统以LRU策略保持非前台进程在缓存里面,比如,当你启动APP时。产生一个进程,可是当你离开这个APP时。进程并未结束。

当你再次进入应用时,进程会从缓存里面高速恢复。


How Your App Should Manage Memory

应用该怎样管理内存

You should apply the following techniques while designing and implementing your app to make it more memory efficient.

为了你的APP更加高效使用内存,你应该採用下列技术:

1、Use services sparingly

保守地使用service

1)If your app needs a service to perform work in the background, do not keep it running unless it’s actively performing a job. Also be careful to never leak your service by failing to stop it when its work is done.

当service的工作完毕后。永远别忘了stop你的service。

2)When you start a service, the system prefers to always keep the process for that service running. This makes the process very expensive because the RAM used by the service can’t be used by anything else or paged out.

当你開始一个服务时,系统将倾向一直保持这个进程。这会使得这个进程非常昂贵。由于被service使用的内存无法再被得到不论什么使用。

3)The best way to limit the lifespan of your service is to use an IntentService, which finishes itself as soon as it’s done handling the intent that started it.

限制service生命周期的最好方式是使用IntentService。它会在完毕任务后自己主动总结自己。


2、Release memory when your user interface becomes hidden

当应用界面不在时,释放内存。

1) When the user navigates to a different app and your UI is no longer visible, you should release any resources that are used by only your UI.

当用户切换到其它应用你的应用UI不再可视时,应该释放全部仅被你的UI使用的资源

2)To be notified when the user exits your UI, implement the onTrimMemory() callback in your Activity classes. You should use this method to listen for the TRIM_MEMORY_UI_HIDDEN level, which indicates your UI is now hidden from view and you should free resources that only your UI uses.

重写onTrimMemory()方法推断TRIM_MEMORY_UI_HIDDEN来监听用户是否离开UI,一旦离开就要释放仅被UI使用的资源。

3)So although you should implement onStop() to release activity resources such as a network connection or to unregister broadcast receivers, you usually should not release your UI resources until you receive onTrimMemory(TRIM_MEMORY_UI_HIDDEN). This ensures that if the user navigates back from another activity in your app, your UI resources are still available to resume the activity quickly.

我们须要在onStop里面释放一些activity资源,如网络连接,广播注冊等。但仅仅有系统回调onTrimMemory(TRIM_MEMORY_UI_HIDDEN)时才释放UI资源。


3、Release memory as memory becomes tight

当内存紧张时释放内存

During any stage of your app’s lifecycle, the onTrimMemory() callback also tells you when the overall device memory is getting low. You should respond by further releasing resources based on the following memory levels delivered by onTrimMemory():

在应用的全部生命周期中,onTrimMemory() 回调能够告诉你设备内存是不是下降着。你应该依据下面反应不同程度内存使用状况的系统回调作出对应的资源释放操作。

1)TRIM_MEMORY_RUNNING_MODERATE

2)TRIM_MEMORY_RUNNING_LOW

3)TRIM_MEMORY_RUNNING_CRITICAL

Also, when your app process is currently cached, you may receive one of the following levels from onTrimMemory():

当你的应用进程当前被缓存时,你也能够接收到下列反应不同程度内存使用状况的系统回调。

1)TRIM_MEMORY_BACKGROUND

2)TRIM_MEMORY_MODERATE

3)TRIM_MEMORY_COMPLETE

When the system begins killing processes in the LRU cache, although it primarily works bottom-up, it does give some consideration to which processes are consuming more memory and will thus provide the system more memory gain if killed

当系统開始杀LRU缓存中的进程时,虽然主要是遵从LRU策略,可是那些占用大量内存的进程也会优先被考虑。


4、Check how much memory you should use

检查你应该使用多少内存

As mentioned earlier, each Android-powered device has a different amount of RAM available to the system and thus provides a different heap limit for each app. You can call getMemoryClass() to get an estimate of your app’s available heap in megabytes. If your app tries to allocate more memory than is available here, it will receive an OutOfMemoryError.

你能够调用getMemoryClass()方法来预计你的应用可用堆内存,假设你的应用使用超过这个量的内存就会造成OOM。

In very special situations, you can request a larger heap size by setting the largeHeap attribute to “true” in the manifest tag. If you do so, you can call getLargeMemoryClass() to get an estimate of the large heap size.

特殊情况下,你能够通过在manifest文件 节点下设置largeHeap属性为true申请更大的堆内存。假设你这样做。能够调用getLargeMemoryClass()来查看可分配到的更大的堆内存。

Additionally, the large heap size is not the same on all devices and, when running on devices that have limited RAM, the large heap size may be exactly the same as the regular heap size.

另外,由分配规则能够知道,即使设了largeHeap,也可能不起作用。


5、Avoid wasting memory with bitmaps

慎重处理Bitmap,避免浪费内存。

參见具体章节。http://developer.android.com/training/displaying-bitmaps/load-bitmap.html


6、Use optimized data containers

使用优化的数据容器

Take advantage of optimized containers in the Android framework, such as SparseArray, SparseBooleanArray, and LongSparseArray.

使用Android API中的优化容器。如SparseArray、SparseBooleanArray,、LongSparseArray等来替代HaspMap等容器。


7、Be aware of memory overhead

清楚内存开销

1)Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.

Enums和静态常量相比通常须要两倍内存,在Android中应该避免使用enums

2)Every class in Java (including anonymous inner classes) uses about 500 bytes of code.

每一个Class使用大概500个字节码

3)Every class instance has 12-16 bytes of RAM overhead.

每一个对象大概有12-16个字节内存的开销

4)Putting a single entry into a HashMap requires the allocation of an additional entry object that takes 32 bytes (see the previous section about optimized data containers).

HashMap每一个key对象须要额外大约32个字节的内存。这也是为什么推荐使用6中提到的优化容器。


8、Be careful with code abstractions

小心抽象编程


9、Use nano protobufs for serialized data

序列化数据时使用nano protobufs


10、Avoid dependency injection frameworks

避免依赖注入框架

these frameworks tend to perform a lot of process initialization by scanning your code for annotations, which can require significant amounts of your code to be mapped into RAM even though you don’t need it.

这些框架会通过扫描你的代码中的注解来进行大量的进程初始化,这会导致相当分量的代码被映射进内存。而这是不必要的。


11、Be careful about using external libraries

慎重使用外部库


12、Optimize overall performance

优化总体表现,这在training doc中有一个专门章节。


13、Use ProGuard to strip out any unneeded code

使用ProGuard来剔除不必要的代码

The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names.Using ProGuard can make your code more compact, requiring fewer RAM pages to be mapped.

使用ProGuard工具来对你的代码进行瘦身、优化和混淆,使得你代码更紧凑,降低内存的使用。


14、Use zipalign on your final APK

使用zipalign工具操作你的终于APK

If you do any post-processing of an APK generated by a build system (including signing it with your final production certificate), then you must run zipalign on it to have it re-aligned. Failing to do so can cause your app to require significantly more RAM, because things like resources can no longer be mmapped from the APK.

你必须用zipalign工具来操作你的终于APK。这会降低你的应用的内存使用,由于一些不必要的资源能够不再须要从APK映射到内存。


15、Analyze your RAM usage

分析你的内存使用

Once you achieve a relatively stable build, begin analyzing how much RAM your app is using throughout all stages of its lifecycle. For information about how to analyze your app, read Investigating Your RAM Usage.

具体信息。看Investigating Your RAM Usage https://developer.android.com/tools/debugging/debugging-memory.html 这一章节。

里面不仅会介绍经常使用的MAT,另一些其它技巧。


16、Use multiple processes

使用多进程

If it’s appropriate for your app, an advanced technique that may help you manage your app’s memory is dividing components of your app into multiple processes.This technique must always be used carefully and most apps should not run multiple processes, as it can easily increase—rather than decrease—your RAM footprint if done incorrectly. It is primarily useful to apps that may run significant work in the background as well as the foreground and can manage those

operations separately.

You can specify a separate process for each app component by declaring the android:process attribute for each component in the manifest file.

当应用的前后台工作分工明白时。能够使用此技巧。但一定要慎重使用。否则会适得其反。


在官方文档中。我们能够得到最准确的一手信息。

Android:管理应用内存的更多相关文章

  1. android 管理Bitmap内存 - 开发文档翻译

    由于本人英文能力实在有限,不足之初敬请谅解 本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接   Managing Bitmap Memory 管理Bitmap内存 In additi ...

  2. (转)Android开发:性能最佳实践-管理应用内存

    翻自:http://developer.android.com/training/articles/memory.html 在任何软件开发环境中,RAM都是宝贵的资源,但在移动操作系统中更加珍贵.尽管 ...

  3. Android应用的内存管理

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

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

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

  5. Android 性能优化——内存篇

    一.android官方一些内存方面的内存tips 1.避免创建不必要的对象. 如尽量避免字符串的加号拼接,可以使用StringBuilder来拼接. 如果需要TextView设置多个字符串片段,可以使 ...

  6. 查找并修复Android中的内存泄露—OutOfMemoryError

    [编者按]本文作者为来自南非约翰内斯堡的女程序员 Rebecca Franks,Rebecca 热衷于安卓开发,拥有4年安卓应用开发经验.有点完美主义者,喜爱美食. 本文系国内ITOM管理平台 One ...

  7. 如何检查 Android 应用的内存使用情况

    Android是为移动设备而设计的,所以应该关注应用的内存使用情况.尽管Android的Dalvik虚拟机会定期执行垃圾回收操作,但这也不意味着就可以忽视应用在何时何处进行内存分配和释放.为了提供良好 ...

  8. 系统剖析Android中的内存泄漏

    [转发]作为Android开发人员,我们或多或少都听说过内存泄漏.那么何为内存泄漏,Android中的内存泄漏又是什么样子的呢,本文将简单概括的进行一些总结. 关于内存泄露的定义,我可以理解成这样 没 ...

  9. 使用新版Android Studio检测内存泄露和性能

    内存泄露,是Android开发者最头疼的事.可能一处小小的内存泄露,都可能是毁于千里之堤的蚁穴.  怎么才能检测内存泄露呢?网上教程非常多,不过很多都是使用Eclipse检测的, 其实1.3版本以后的 ...

  10. Android DDMS检测内存泄露

    Android DDMS检测内存泄露 DDMS是Android开发包中自带工具,可以测试app性能,用于发现内存问题. 1.环境搭建 参考之前发的Android测试环境搭建相关文章,这里不再复述: 2 ...

随机推荐

  1. vue下面的scoped

    scope这个属性限制了下面的css代码的作用域只在当前组件中生效,此时直接去更改elementui的属性,浏览器搜索不到这个元素的最外层的父级,于是这个东西不会生效

  2. django框架-Admin管理站点搭建

    在django框架中,admin基本上算是已经写好了的,拿过来进行简单的处理即可以使用的,相对于flask来说已经是相当的便捷了. 在使用中,步骤如下: 1.管理界面本地化:即将英文标题等的变成中文, ...

  3. Html标记语言学习一2017年6月12日

    今天主要学习了 frame的用法. <frameset> 可以将网页分成几个不同的部分 使用 cols  和  rows 两种标记.前者是列,后者是行 <frame/>  单标 ...

  4. 链表(list)--c实现

    做c的开发有1年多了,期间写过c++,感觉基础不够好,补上去,不丢人.o(^▽^)o to better myself. #include <stdio.h> #include <s ...

  5. Linux一些简单命令

    1.安装gvim:sudo apt-get install vim-gtk vim和gvim相同,只是后者比前者多了一个界面,此界面可以用来保存.新建.查找等. 三种模式,insert(i),norm ...

  6. Oracle11g R2创建PASSWORD_VERIFY_FUNCTION相应password复杂度验证函数步骤

    Oracle11g R2创建PASSWORD_VERIFY_FUNCTION相应密码复杂度验证函数步骤 运行測试环境:数据库服务器Oracle Linux 5.8 + Oracle 11g R2数据库 ...

  7. Dynamics CRM2013 Form利用window.location.reload()进行全局刷新带来的问题及解决的方法

    CRM2013以后.表单的保存后变成了局部刷新而非全局刷新,但非常多情况下我们须要刷新整个页面.通过刷新页面来使脚本运行或者业务规则运行来实现某些业务效果,一般我们会使用window.location ...

  8. SGU 210 Acdream 1227 Beloved Sons KM

    题目链接:点击打开链接 题意: 给定n个人 每一个人的点权 以下n行i行表示第i个人能够获得哪些数(数字从1-n.且不能反复分配) 若这个人获得了数字则你能够获得他的权值. 要你能获得的权值和最大. ...

  9. linux程序设计——个人总结

    linux程序设计--个人总结 到今天为止,<linux程序设计>学习基本完毕了.从五月下旬開始接触linux,学习安装Ubuntu14.04,六月份開始学习<linux程序设计&g ...

  10. LeakCanary:简单粗暴的内存泄漏检測工具

    差点儿每一个程序猿在开发的过程中都会遇到内存泄漏.那么我们怎样检測到app是否哪里出现内存泄漏呢?square公司推出了一款简单粗暴的检測内存泄漏的工具-- LeakCanary 什么是内存泄漏? 内 ...