標籤:
借鑒:大苞米的部落格(http://blog.csdn.net/a396901990)
一.記憶體溢出(OOM--out of memory)
(1)記憶體溢出引發的問題展現:
1.程式卡頓,響應速度慢(記憶體佔用高時JVM虛擬機器會頻繁觸發GC)
2.莫名消失(當你的程式所佔記憶體越大,它在背景時候就越可能被幹掉。反之記憶體佔用越小,在後台存在的時間就越長)
3.直接崩潰(OutOfMemoryError)
(2)記憶體溢出的原因
因為app的每個進程或者每個虛擬機器有個最大記憶體限制,如果申請的記憶體資源超過這個限制,系統就會拋出OOM錯誤。OOM跟整個裝置的剩餘記憶體沒太大關係,跟系統運行記憶體有一定關係。比如比較早的android系統的一個虛擬機器最多16M記憶體,當一個app啟動後,虛擬機器不停的申請記憶體資源來裝載圖片,當超過記憶體上限時就出現OOM。
android的記憶體組成:
APP記憶體由 dalvik記憶體 和 native記憶體 2部分組成,dalvik也就是java堆,建立的對象就是就是在這裡分配的,而native是通過c/c++方式申請的記憶體,Bitmap就是以這種方式分配的。(android3.0以後,系統都預設通過dalvik分配的,native作為堆來管理)。這2部分加起來不能超過android對單個進程,虛擬機器的記憶體限制。
(3)android系統為什麼要設定app的記憶體限定
1.迫使開發人員更合理的分配記憶體。限制每個應用的可用記憶體上限,可以放置某些應用程式惡意或者無意的使用過多的記憶體。而導致其它應用無法正常運行。Android是有多進程的,如果一個進程(就是一個應用)耗費過多的記憶體,其他應用就無法運行了。因為有了限制,使得開發人員必須好好利用有限資源,最佳化資源的使用。
2.螢幕顯示內容有限。即使有萬千圖片千萬資料需要使用到,但在特定時刻需要展示給使用者看的總是有限的,因為螢幕顯示就那麼大,上面可以放的資訊就是很有限的。大部分資訊都是處於準備顯示狀態,所以沒必要給予太多heap記憶體。也就是說出現 OOM現象,絕大部分原因是我們的程式設計上有問題,需要最佳化 。最佳化方法很多,比如通過時間換空間,不停的載入要用的的圖片,不停的回收不用的圖片,把大圖片解析成適合手機螢幕大小的圖片等。
3.davlik虛擬機器的設計。android上的app使用獨立虛擬機器運行,每開一個應用就會開啟至少一個獨立的虛擬機器。這樣可以避免虛擬機器崩潰導致整個系統崩潰,同時代價就是需要浪費更多的記憶體。這樣設計保證了android的穩定性。
二.GC自動回收記憶體
Android的gc會按照特定的演算法回收程式不用的記憶體資源,避免app的記憶體申請約積越多,但是gc一般回收的資源是那些無主的對象記憶體或者軟引用的資源,或者更軟引用的引用資源。
(1)優點:
1.減輕編程負擔,提高效率
c、c++中的記憶體回收都是程式員手動操作,否則其中的資源將消耗,造成資源的浪費甚至崩潰。但手工回收記憶體往往是一項複雜而艱巨的工作。而java語言採用一種動態儲存裝置管理技術,它自動地釋放不再被程式引用的對象,按照特定的垃圾收集演算法來實現資源自動回收的功能。當一個對象不再被引用的時候,記憶體回收它佔領的空間,以便空間被後來的新對象使用。
2.消除堆記憶體控制項片段
由於建立對象和垃圾收集器釋放丟棄對象所佔的記憶體空間,記憶體會出現片段。片段是分配給對象的記憶體塊之間的空閑記憶體洞。磁碟重組將所佔用的堆記憶體移到堆的一端,JVM將整理出的記憶體配置給新的對象。
(2)缺點
佔用資源,不可預知,不可確定,不可操作。大學老師說了一句很生動形象的話,“只拉不收拾”。這是一個很不好的習慣,在編程過程中,還是應該有一定的編程素養。用了什麼,在不需要的時候就及時銷毀。
三.查看app記憶體配置情況
1.通過DDMS中的heap選項卡監視記憶體情況:
Heap視圖中部有一個叫做data object, 即資料對象,也就是我們的程式中大量存在的類類型的對象。
在data object一行中有一列是"Total Size", 其值就是當前進程中所有Java資料對象的記憶體總量。如果代碼中存在沒有釋放對象引用的情況,則data object的"Total Size"值在每次gc後不會有美線的回落。隨著操作次數的增加"Total Size"的值會越來越大。直到到達一個上限 後導致進程被kill掉。
2.在App裡面我們可以通過totalMemory與freeMemory
3.adb shell dumpsys meminfo com.android.demo
未完,待續。。。
android 記憶體問題