ANDROID記憶體優化(大彙總——上)
轉載請註明本文出自大苞米的部落格(http://blog.csdn.net/a396901990),謝謝支援!
寫在最前:
本文的思路主要借鑑了2014年AnDevCon開發者大會的一個演講PPT,加上把網上搜集的各種記憶體零散知識點進行彙總、挑選、簡化後整理而成。
所以我將本文定義為一個工具類的文章,如果你在ANDROID開發中遇到關於記憶體問題,或者馬上要參加面試,或者就是單純的學習或複習一下記憶體相關知識,都歡迎閱讀。(本文最後我會盡量列出所參考的文章)。
一般Java在記憶體分配時會涉及到以下區域:
暫存器(Registers):速度最快的儲存場所,因為暫存器位於處理器內部,我們在程式中無法控制
棧(Stack):存放基本型別的資料和物件的引用,但物件本身不存放在棧中,而是存放在堆中
堆(Heap):堆記憶體用來存放由new建立的物件和陣列。在堆中分配的記憶體,由Java虛擬機器的自動垃圾回收器(GC)來管理。
靜態域(static field): 靜態儲存區域就是指在固定的位置存放應用程式執行時一直存在的資料,Java在記憶體中專門劃分了一個靜態儲存區域來管理一些特殊的資料變數如靜態的資料變數
常量池(constant pool):虛擬機器必須為每個被裝載的型別維護一個常量池。常量池就是該型別所用到常量的一個有序集和,包括直接常量(string,integer和floating point常量)和對其他型別,欄位和方法的符號引用。
非RAM儲存:硬碟等永久儲存空間
堆疊特點對比:
由於篇幅原因,下面只簡單的介紹一下堆疊的一些特性。
棧:當定義一個變數時,Java就在棧中為這個變數分配記憶體空間,當該變數退出該作用域後,Java會自動釋放掉為該變數所分配的記憶體空間,該記憶體空間可以立即被另作他用。
堆:當堆中的new產生陣列和物件超出其作用域後,它們不會被釋放,只有在沒有引用變數指向它們的時候才變成垃圾,不能再被使用。即使這樣,所佔記憶體也不會立即釋放,而是等待被垃圾回收器收走。這也是Java比較佔記憶體的原因。
棧:存取速度比堆要快,僅次於暫存器。但缺點是,存在棧中的資料大小與生存期必須是確定的,缺乏靈活性。
堆:堆是一個執行時資料區,可以動態地分配記憶體大小,因此存取速度較慢。也正因為這個特點,堆的生存期不必事先告訴編譯器,而且Java的垃圾收集器會自動收走這些不再使用的資料。
棧:棧中的資料可以共享, 它是由編譯器完成的,有利於節省空間。
例如:需要定義兩個變數int a = 3;int b = 3;
編譯器先處理int a = 3;首先它會在棧中建立一個變數為a的引用,然後查詢棧中是否有3這個值,如果沒找到,就將3存放進來,然後將a指向3。接著處理int b = 3;在建立完b的引用變數後,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。這時,如果再讓a=4;那麼編譯器會重新搜尋棧中是否有4值,如果沒有,則將4存放進來,並讓a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。
堆:例如上面棧中a的修改並不會影響到b, 而在堆中一個物件引用變數修改了這個物件的內部狀態,會影響到另一個物件引用變數。
記憶體耗用名詞解析:
VSS - Virtual Set Size 虛擬耗用記憶體(包含共享庫佔用的記憶體)
RSS - Resident Set Size 實際使用實體記憶體(包含共享庫佔用的記憶體)
PSS - Proportional Set Size 實際使用的實體記憶體(比例分配共享庫佔用的記憶體)
USS - Unique Set Size 程式獨自佔用的實體記憶體(不包含共享庫佔用的記憶體)
一般來說記憶體佔用大小有如下規律:VSS >= RSS >= PSS >= USS
OOM:
記憶體洩露可以引發很多的問題:
1.程式卡頓,響應速度慢(記憶體佔用高時JVM虛擬機器會頻繁觸發GC)
2.莫名消失(當你的程式所佔記憶體越大,它在後臺的時候就越可能被幹掉。反之記憶體佔用越小,在後臺存在的時間就越長)
3.直接崩潰(OutOfMemoryError)
ANDROID記憶體面臨的問題:
1.有限的堆記憶體,原始只有16M
2.記憶體大小消耗等根據裝置,作業系統等級,螢幕尺寸的不同而不同
3.程式不能直接控制
4.支援後臺多工處理(multitasking)
5.執行在虛擬機器之上
5R:
本文主要通過如下的5R方法來對ANDROID記憶體進行優化:
1.Reckon(計算)
首先需要知道你的app所消耗記憶體的情況,知己知彼才能百戰不殆
2.Reduce(減少)
消耗更少的資源
3.Reuse(重用)
當第一次使用完以後,儘量給其他的使用
5.Recycle(回收)
返回資源
4.Review(檢查)
回顧檢查你的程式,看看設計或程式碼有什麼不合理的地方。
Reckon (計算):
瞭解自己應用的記憶體使用情況是很有必要的。如果當記憶體使用過高的話就需要對其進行優化,因為更少的使用記憶體可以減少ANDROID系統終止我們的程式的機率,也可以提高多工執行效率和體驗效果。
下面從系統記憶體(system ram)和堆記憶體(heap)兩個方面介紹一些檢視和計算記憶體使用情況的方法:
System Ram(系統記憶體):
觀察和計算系統記憶體使用情況,可以使用Android提供給我們的兩個工具procstats,meminfo。他們一個側重於後臺的記憶體使用,另一個是執行時的記憶體使用。
Process Stats:
Heap(堆記憶體):
在程式中可以使用如下的方法去查詢記憶體使用情況
ActivityManager#getMemoryClass()
查詢可用堆記憶體的限制
3.0(HoneyComb)以上的版本可以通過largeHeap=“true”來申請更多的堆記憶體(不過這算作“作弊”)
android.os.Debug#getMemoryInfo(Debug.MemoryInfo memoryInfo)
得到的MemoryInfo中可以檢視如下Field的屬性:
android.os.Debug#getNativeHeapSize()
返回的是當前程式navtive堆本身總的記憶體大小
android.os.Debug#getNativeHeapAllocatedSize()
返回的是當前程式navtive堆中已使用的記憶體大小
android.os.Debug#getNativeHeapFreeSize()
返回的是當前程式navtive堆中已經剩餘的記憶體大小
Memory Analysis Tool(MAT):
通常記憶體洩露分析被認為是一件很有難度的工作,一般由團隊中的資深人士進行。不過,今天我們要介紹的 MAT(Eclipse Memory Analyzer)被認為是一個“傻瓜式“的堆轉儲檔案分析工具,你只需要輕輕點選一下滑鼠就可以生成一個專業的分析報告。
如下圖:
關於詳細的MAT使用我推薦下面這篇文章:使用 Eclipse Memory Analyzer 進行堆轉儲檔案分析
寫在最後:
我準備將文章分為上、中、下三部分。現在已經全部完成:
記憶體簡介,Recoken(計算)請看:ANDROID記憶體優化(大彙總——上)
Reduce(減少),Reuse(重用) 請看:ANDROID記憶體優化(大彙總——中)
Recycle(回收), Review(檢查) 請看:ANDROID記憶體優化(大彙總——全)
寫這篇文章的目的就是想弄一個大彙總,將零散的記憶體知識點總結一下,如果有錯誤、不足或建議都希望告訴我。
參考文章:
AnDevCon開發者大會演講PPT:Putting Your App on a Memory Diet
深入Java核心 Java記憶體分配原理精講(http://developer.51cto.com/art/201009/225071.htm)
Process Stats: Understanding How Your App Uses RAM(http://blog.csdn.net/a396901990/article/details/38390135)
Android中如何檢視記憶體(http://blog.csdn.net/hudashi/article/details/7050897)
Android記憶體效能優化(內部資料總結)(http://www.2cto.com/kf/201405/303276.html)
相關文章
- ANDROID記憶體優化(大彙總——中)Android記憶體優化
- ANDROID記憶體優化(大彙總——下)Android記憶體優化
- Android 效能優化之記憶體洩漏檢測以及記憶體優化(上)Android優化記憶體
- Android記憶體優化Android記憶體優化
- Android 記憶體優化Android記憶體優化
- 記憶體使用總結篇 -- Android 記憶體優化第五彈記憶體Android優化
- Android效能優化 - 記憶體優化Android優化記憶體
- Android效能優化篇之記憶體優化--記憶體洩漏Android優化記憶體
- Android 效能優化之記憶體優化Android優化記憶體
- Android記憶體優化之記憶體快取Android記憶體優化快取
- Android Note - 記憶體優化Android記憶體優化
- android 記憶體優化篇Android記憶體優化
- Android對Bitmap的記憶體優化方案總結Android記憶體優化
- Android記憶體優化(一):Java記憶體區域Android記憶體優化Java
- Android記憶體優化之圖片優化Android記憶體優化
- 淺談Android記憶體優化Android記憶體優化
- Android記憶體優化全解析Android記憶體優化
- Android記憶體優化雜談Android記憶體優化
- android,記憶體優化詳解Android記憶體優化
- Android記憶體分析和調優(上)Android記憶體
- Android 效能優化之記憶體洩漏檢測以及記憶體優化(下)Android優化記憶體
- Android 效能優化之記憶體洩漏檢測以及記憶體優化(中)Android優化記憶體
- Android APP 記憶體優化之圖片優化AndroidAPP記憶體優化
- [譯] Android效能優化:APK瘦身方式大彙總Android優化APK
- android 關於記憶體優化的一些總結Android記憶體優化
- Android記憶體洩漏監控和優化技巧總結Android記憶體優化
- Android應用記憶體優化方式Android記憶體優化
- Android效能優化之記憶體篇Android優化記憶體
- Android記憶體優化(三)避免可控的記憶體洩漏Android記憶體優化
- Android記憶體優化(五)詳解記憶體分析工具MATAndroid記憶體優化
- Android記憶體優化——記憶體洩露檢測分析方法Android優化記憶體洩露
- Android 效能優化(四)之記憶體優化實戰Android優化記憶體
- Redis 記憶體優化神技,小記憶體儲存大資料Redis記憶體優化大資料
- Android 是如何管理 App 記憶體的 — Android 記憶體優化第二彈AndroidAPP記憶體優化
- Android 是如何管理 App 記憶體的 -- Android 記憶體優化第二彈AndroidAPP記憶體優化
- android效能評測與優化-記憶體Android優化記憶體
- android記憶體管理機制與優化Android記憶體優化
- Android效能優化(三)之記憶體管理Android優化記憶體