Android中的記憶體管理機制以及正確的使用方式

來源:互聯網
上載者:User

標籤:

概述

        從作業系統的角度來說,記憶體就是一塊資料存放區地區,屬於可被作業系統調度的資源。現代多任務(進程)的作業系統中,記憶體管理尤為重要,作業系統需要為每一個進程合理的分配記憶體資源,所以可以從兩方面來理解作業系統的記憶體管理機制。

        第一:分配機制。為每一個進程分配一個合理的記憶體大小,保證每一個進程能夠正常的運行,不至於記憶體不夠使用或者每個進程佔用太多的記憶體。

        第二:回收機制。在系統記憶體不足打的時候,需要有一個合理的回收再分配的機制,以保證新的進程可以正常運行。回收的時候就要殺死那些正在佔有記憶體的進程,作業系統需要提供一個合理的殺死這些進程的機制,以保證更少的副作用。

        而作為一個多進程的作業系統,Android系統對記憶體的管理,也是有一套自己的方法的。跟PC不一樣的是,Android作為一個移動作業系統,一般情況下,記憶體資源會比PC更少,所以就需要更加謹慎的管理記憶體。

 

 

 

Android中的記憶體管理機制分配機制

        Android為每個進程分配記憶體的時候,採用了彈性的分配方式,也就是剛開始並不會一下分配很多記憶體給每個進程,而是給每一個進程分配一個“夠用”的量。這個量是根據每一個裝置實際的實體記憶體大小來決定的。隨著應用的運行,可能會發現當前的記憶體可能不夠使用了,這時候Android又會為每個進程分配一些額外的記憶體大小。但是這些額外的大小並不是隨意的,也是有限度的,系統不可能為每一個App分配無限大小的內除。

        Android系統的宗旨是最大限度的讓更多的進程存活在記憶體中,因為這樣的話,下一次使用者再啟動應用,不需要重新建立進程,只需要恢複已有的進程就可以了,減少了應用的啟動時間,提高了使用者體驗。

 

回收機制

        Android對記憶體的使用方式是“盡最大限度的使用”,這一點繼承了Linux的優點。Android會在記憶體中儲存儘可能多的資料,即使有些進程不再使用了,但是它的資料還被儲存在記憶體中,所以Android現在不推薦顯式的“退出”應用。因為這樣,當使用者下次再啟動應用的時候,只需要恢複當前進程就可以了,不需要重新建立進程,這樣就可以減少應用的啟動時間。只有當Android系統發現記憶體不夠使用,需要回收記憶體的時候,Android系統就會需要殺死其他進程,來回收足夠的記憶體。但是Android也不是隨便殺死一個進程,比如說一個正在與使用者互動的進程,這種後果是可怕的。所以Android會有限清理那些已經不再使用的進程,以保證最小的副作用。

        Android殺死進程有兩個參考條件:

        進程優先順序:

        Android為每一個進程分配了優先順序的概念,優先順序越低的進程,被殺死的機率就更大。Android中總共有5個進程優先順序。具體含義這裡不再給出。

        前台進程:正常不會被殺死

        可見進程:正常不會被殺死

        服務進程:正常不會被殺死

        後台進程:存放於一個LRU緩衝列表中,先殺死處於列表尾部的進程

        空進程:正常情況下,為了平衡系統整體效能,Android不儲存這些進程

 

        回收收益:

        當Android系統開始殺死LRU緩衝中的進程時,系統會判斷每個進程殺死後帶來的回收收益。因為Android總是傾向於殺死一個能回收更多記憶體的進程,從而可以殺死更少的進程,來擷取更多的記憶體。殺死的進程越少,對使用者體驗的影響就越小。

 

 

 

 

官方推薦的App記憶體使用量方式是什麼樣的?1、當Service完成任務後,盡量停止它。

        因為有Service組件的進程,優先順序最低也是服務進程,這會影響到系統的記憶體回收。IntentService可以很好地完成這個任務。

2、在UI不可見的時候,釋放掉一些只有UI使用的資源。

        系統會根據onTrimMemory()回調方法的TRIM_MEMORY_UI_HIDDEN等級的事件,來通知App UI已經隱藏了。

3、在系統記憶體緊張的時候,儘可能多的釋放掉一些非重要資源。

        系統會根據onTrimMemory()回調方法來通知記憶體緊張的狀態,App應該根據不同的記憶體緊張等級,來合理的釋放資源,以保證系統能夠回收更多記憶體。當系統回收到足夠多的記憶體時,就不用殺死進程了。

4、檢查自己最大可用的記憶體大小。

        這對一些緩衝架構很有用,因為正常情況下,緩衝架構的緩衝池大小應當指定為最大記憶體的百分比,這樣才能更好地適配更多的裝置。通過getMemoryClass()和getLargeMemoryClass()來擷取可用記憶體大小的資訊。

5、避免濫用Bitmap導致的記憶體浪費。

        根據當前裝置的解析度來壓縮Bitmap是一個不錯的選擇,在使用完Bitmap後,記得要使用recycle()來釋放掉Bitmap。使用軟引用或者弱引用來引用一個Bitmap,使用LRU緩衝來對Bitmap進行緩衝。

6、使用針對記憶體最佳化過的資料容器。

        針對行動裝置記憶體有限的問題,Android提供了一套針對記憶體最佳化過的資料容器,來替代JDK原生提供的資料容器。但是缺點就是,時間複雜度被提高了。比如SparseArray、SparseBooleanArray、LongSparseArray、

7、意識到記憶體的過度消耗。

        Enum類型佔用的記憶體是常量的兩倍多,所以避免使用enum,直接使用常量。

        每一個Java的類(包括匿名內部類)都需要500Byte的代碼。

        每一個類的執行個體都有12-16 Byte的額外記憶體消耗。

        注意類似於HashMap這種,內部還需要產生Class的資料容器,這會消耗更多記憶體。

8、抽象代碼也會帶來更多的記憶體消耗。

        如果你的“抽象”設計實際上並沒有帶來多大好處,那麼就不要使用它。

9、使用nano protobufs 來序列化資料。

        Google設計的一個語言和平台中立打的序列化協議,比XML更快、更小、更簡單。

10、避免使用依賴注入的架構。

        依賴注入的架構需要開啟額外的服務,來掃描App中代碼的Annotation,所以需要額外的系統資源。

11、使用ZIP對齊的APK。

        對APK做Zip對齊,會壓縮其內部的資源,運行時會佔用更少的記憶體。

12、使用多進程。

 

 

 

一個符合Android記憶體管理機制的App應該是什麼樣的?

        一個遵循Android記憶體管理機制的App。應該具有如下幾個特點:

        1、更少的佔用記憶體。

        2、在合適的時候,合理的釋放系統資源。

        3、在系統記憶體緊張的情況下,能釋放掉大部分不重要的資源,來為Android系統提供可用的記憶體。

        4、能夠很合理的在特殊生命週期中,儲存或者還原重要資料,以至於系統能夠正確的重新恢複該應用。

 

 

 

App為什麼要符合該記憶體管理機制?這樣做有什麼好處?

        一個遵循Android的記憶體管理機制的App,在Android系統中,就是一個好的公民,那麼系統自然是傾向於保護這些良民,而去殺死那些素質不高的人。所以符合Android記憶體管理機制,對Android系統和App來說,是一個雙贏的過程。如果每一個App都遵循這種規則,那麼Android系統就會更加流暢,也會帶來更好的體驗,而App可以更長時間的駐留於記憶體中。

 

 

 

在這種管理方式下,如何編寫符合Android記憶體管理機制的App?

        主要是參考官方推薦的記憶體使用量方式,來設計和編寫App。

        避免建立不必要的對象。

        在合適的生命週期中,合理的管理資源。

        在系統記憶體不足時,主動釋放更多的資源。

 

 

 

編寫Android應用時,如何更少的使用記憶體資源?

        避免建立不需要的對象。

        比如使用StringBuffer來代替很多個String相加的操作。

        使用原始類型來代替封裝類型,int比Integer佔用更少的資源。

        兩個並行的屬性數組,優於一個包含這兩個屬性的對象的數組。這個在設計資料容器的時候會有意義,比如類A有兩個屬性A(int, String),使用 int[] 和 String[] 優於 A[]。

        使用常量代替enum。

        少用封裝類,能夠使用原始類型的,就使用原始類型。

 

 

 

App如果真的需要很多記憶體怎麼辦?多進程

        把消耗記憶體過大的模組,或者需要長期在後台啟動並執行模組,移入到單獨的進程中運行。Android會為每一個進程單獨分配記憶體,所以理論上App就可以使用到更多的記憶體。但是多進程是一把雙刃劍,錯誤的使用,會帶來其他很多的問題,這裡不再詳細談這個話題。

申請大記憶體

        在<application>標籤中,把largeHeap設定為true,Android系統會為該應用額外分配記憶體。但是不要濫用這個方法。如果一個App真的需要大記憶體,比如需要開啟很多大圖片的應用,可以使用這種方式。千萬不要因為OOM而使用這種方法,這個時候更應該去檢查App的代碼是否不合理。

 

 

 

開發人員應該注意的App記憶體管理方式?記憶體溢出

        記憶體溢出,就是OOM,也就是記憶體不夠用了。有一個典型的例子就是載入了很多沒有經過壓縮的Bitmap到記憶體中,這些Bitmap很大,但是又真的在被使用,必須要在記憶體中,所以這個時候記憶體就不夠用了。這個時候,App再申請更多記憶體的時候就不行了,系統會拋出OOM。

        解決這種問題:1、減少每個對象佔用的記憶體,比如壓縮圖片。2、申請大記憶體。

記憶體泄露

        記憶體泄露,就是Memory Leak,也就是本來該被GC回收後還給系統的記憶體,並沒有被GC。多數是因為不合理的對象引用,當一個對象不再使用的時候,由於代碼問題,沒有正確的釋放引用,就導致了記憶體泄露。

        解決這種問題:1、通過各種記憶體分析工具,比如MAT,分析運行時的記憶體映像檔案,找出造成記憶體泄露的代碼,然後修改掉。2、適當的使用WeakReference。

 

 

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.