Android Memory Leak & OOM 分析

來源:互聯網
上載者:User

標籤:android   記憶體流失   oom   記憶體管理   

1、Android 進程管理&記憶體Android主要應用在嵌入式裝置當中,而嵌入式裝置由於一些眾所周知的條件限制,通常都不會有很高的配置,特別是記憶體是比較有限的。如果我們編寫的代 碼當中有太多的對記憶體使用量不當的地方,難免會使得我們的裝置運行緩慢,甚至是死機。為了能夠使得Android應用程式安全且快速的運行,Android 的每個應用程式都會使用一個專有的Dalvik虛擬機器執行個體來運行,它是由Zygote服務進程演變過來的,也就是說每個應用程式都是在屬於自己的進程中啟動並執行。一方面,如果程式在運行過程中出現了記憶體流失的問題,僅僅會使得自己的進程被殺掉,而不會影響其他進程(如果是system_process 等系統進程出問題的話,則會引起系統重啟)。另一方面Android為不同類型的進程分配了不同的記憶體使用量上限,如果應用進程使用的記憶體超過了這個上限, 則會被系統視為記憶體流失,從而被殺掉。

同時,Android會為每個應用程式分配一個單獨的LINUX使用者。Android會盡量保留一個正在運行進程,只在記憶體資源出現不足時,Android會嘗試停止一些進程從而釋放足夠的資源給其他新的進程使用, 也能保證使用者正在訪問的當前進程有足夠的資源去及時地響應使用者的事件。Android會根據進程中啟動並執行組件類別以及組件的狀態來判斷該進程的重要性,Android會首先停止那些不重要的進程。按照重要性從高到低一共有五個層級就是我們常說的:前台進程、可見進程、服務進程、後台進程、空進程。
2、單個應用可用的最大記憶體Android裝置出廠以後,java虛擬機器對單個應用的最大記憶體配置就確定下來了,超出這個值就會OOM。這個屬性值是定義在/system/build.prop檔案中的
dalvik.vm.heapstartsize=8m
它表示堆分配的初始大小,它會影響到整個系統對RAM的使用程度,和第一次使用應用時的流暢程度。
它值越小,系統ram消耗越慢,但一些較大應用一開始不夠用,需要調用gc和堆調整策略,導致應用反應較慢。它值越大,這個值越大系統ram消耗越快,但是應用更流暢。

dalvik.vm.heapgrowthlimit=64m // 單個應用可用最大記憶體
主要對應的是這個值,它表示單個進程記憶體被限定在64m,即程式運行過程中實際只能使用64m記憶體,超出就會報OOM。(僅僅針對dalvik堆,不包括native堆)

dalvik.vm.heapsize=384m//heapsize參數表示單個進程可用的最大記憶體,但如果存在heapgrowthlimit參數,則以heapgrowthlimit為準.
heapsize表示不受控情況下的極限堆,表示單個虛擬機器或單個進程可用的最大記憶體。而android上的應用是帶有獨立虛擬機器的,也就是每開一個應用就會開啟一個獨立的虛擬機器(這樣設計就會在單個程式崩潰的情況下不會導致整個系統的崩潰)。
注意:在設定了heapgrowthlimit的情況下,單個進程可用最大記憶體為heapgrowthlimit值。在android開發中,如果要使用大堆,需要在manifest中指定android:largeHeap為true,這樣dvm heap最大可達heapsize。

不同裝置,這些個值可以不一樣。一般地,廠家針對裝置的配置情況都會適當的修改/system/build.prop檔案來調高這個值。隨著裝置硬體效能的不斷提升,從最早的16M限制(G1手機)到後來的24m,32m,64m等,都遵循Android架構對每個應用的最小記憶體大小限制,參考http://source.android.com/compatibility/downloads.html 3.7節。

通過代碼查看每個進程可用的最大記憶體,即heapgrowthlimit值:
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int memClass = activityManager.getMemoryClass();//64,以m為單位

3、為什麼會記憶體泄露  android通過android虛擬機器來管理記憶體,程式員只管申請記憶體建立對象,建立完不再需要關心怎麼釋放對象記憶體,一切由虛擬機器幫你搞定,然而虛擬機器回收對象是有條件的。這裡簡單敘述下java記憶體管理機制(註:網上有很多關於java管理記憶體的文章,其中記憶體回收演算法很發雜,演算法也有很多,大家可以自己去研究下),java虛擬機器維護著一張當前對象關係的object tree,當GC發生時,虛擬機器會去掃描當前對象樹,發現通過任何reference chain(引用鏈)無法訪問某個對象的時候,該對象即被回收。名詞GC Roots正是分析這一過程的起點,例如JVM自己確保了對象的可到達性(那麼JVM就是GC Roots),所以GC Roots就是這樣在記憶體中保持對象可到達性的,一旦不可到達,即被回收。通常GC Roots是一個在current thread(當前線程)的call stack(調用棧)上的對象(例如方法參數和局部變數),或者是線程自身或者是system class loader(系統類別載入器)載入的類以及native code(本地代碼)保留的使用中的物件。所以GC Roots是分析對象為何還存活於記憶體中的利器。知道了什麼樣的對象GC才會回收後,再來學習下對象引用都包含哪些吧。
Java中包含4種對象引用:
強引用: 通常我們編寫的代碼都是Strong Ref,eg :Person person = new Person("sunny");不管系統資源有多緊張,強引用的對象都絕對不會被回收,即使他以後不再用到。
軟引用:只要有足夠的記憶體,就一直保持對象。一般可用來實現緩衝,通過java.lang.r.efSoftReference類實現。記憶體非常緊張的時候會被回收,其他時候不會被回收,所以在使用之前需要判空,從而判斷當前時候已經被回收了。
弱引用:通過WeakReference類實現,eg : WeakReference p = new WeakReference(new Person("Rain"));不管記憶體是否足夠,系統記憶體回收時必定會回收。
虛引用:不能單獨使用,主要是用於追蹤對象被記憶體回收的狀態。通過PhantomReference類和引用隊列ReferenceQueue類聯合使用實現。
我們可能還需要瞭解shallow size、retained size概念,簡單來說,Shallow size就是對象本身佔用記憶體的大小,不包含對其他對象的引用,也就是對象頭加成員變數(不是成員變數的值)的總和。在32位系統上,對象頭佔用8位元組,int佔用4位元組,不管成員變數(對象或數組)是否引用了其他對象(執行個體)或者賦值為null它始終佔用4位元組。故此,對於String對象執行個體來說,它有三個int成員(34=12位元組)、一個char[]成員(14=4位元組)以及一個對象頭(8位元組),總共34 +14+8=24位元組。根據這一原則,對String a=”rosen jiang”來說,執行個體a的shallow size也是24位元組。Retained size是該對象自己的shallow size,加上只能從該對象能直接或間接訪問到對象的shallow size之和。換句話說,retained size是該對象被GC之後所能回收到記憶體的總和。為了更好的理解retained size,我們來看個例子。
    圖1
假設記憶體中對象之間的參考關聯性可以看成圖1的方式,可以看到 GC正是reference chain的起點。從obj1入手,中藍色節點代表僅僅只有通過obj1才能直接或間接訪問的對象。因為可以通過GC Roots訪問,所以左圖的obj3不是藍色節點;而在右圖卻是藍色,因為它已經被包含在retained集合內。所以對於左圖,obj1的retained size是obj1、obj2、obj4的shallow size總和;右圖的retained size是obj1、obj2、obj3、obj4的shallow size總和。
相信了有以上的這些基礎概念,我們應該對java記憶體管理有了一個初步的瞭解,下面回到主題。。。為什麼會記憶體泄露呢,根本原因就是一個永遠不會被使用的對象,因為一些引用沒有斷開,沒有滿足GC條件,導致不會被回收,這就造成了記憶體泄露。如果我們的java運行很久,而這種記憶體泄露不斷的發生,最後就沒記憶體可用了,最終就是我們看到的OOM錯誤。雖然android的記憶體泄露做到了應用程式層級的泄露(android中的每個應用程式都是獨立運行在單獨進程中的,每個應用進程都由虛擬機器指定了一個記憶體上限值,一旦記憶體佔用值超過這個上限值,就會發生oom錯誤,進程被強制kill掉,kill掉的進程記憶體會被系統回收),但是對於一名測試工程師,我們需要對程式品質負責,絕對不能放過任何的記憶體泄露。

4、常見的MemoryLeak分析4.1 頻繁的使用static關鍵字修飾4.2 BitMap隱患4.2.1及時recycle4.2.2設定一定的採樣率4.3 Cursor及時關閉4.4 convertView緩衝4.5 組件都有生命週期,資源在對應的生命週期中銷毀

Android Memory Leak & OOM 分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.