Android:管理應用記憶體

來源:互聯網
上載者:User

標籤:android   記憶體管理   

所有內容均來源於官方文檔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:管理應用記憶體

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.