Android內存泄露調試_第1頁
Android內存泄露調試_第2頁
Android內存泄露調試_第3頁
Android內存泄露調試_第4頁
Android內存泄露調試_第5頁
已閱讀5頁,還剩13頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Android 內存泄漏調試 一、概述 如果我們編寫的代碼當中有太多的對內存使用不當的地方,難免會使得我們的設備運行緩慢,甚至是死機。為了能夠使得 Android 應用程序安全且快速的運行, Android 的每個應用程序都會使用一個專有的 Dalvik 虛擬機實例來運行,即每個應用程序都是在屬于自己的進程中運行的。一方面,如果程序在運行過程中出現了內存泄漏的問題,僅僅會使得自己的 進程被 kill 掉,而不會影響其他進程(如果是 system_process 等系統(tǒng)進程出問題的話,則會引起系統(tǒng)重啟)。另一方面 Android 為不同類型的進程分配了不同

2、的內存使用上限,如果應用進程使用的內存超過了這個上限,則會被系統(tǒng)視為內存泄漏,從而被 kill 掉。Android 為應用進程分配的內存上限如下所示: 位置: /ANDROID_SOURCE/system/core/rootdir/init.rc 部分腳本# Define the oom_adj values for the classes of processes that can be killed by the kernel.# These are used in ActivityManagerService.setprop ro.FOREGROUND_APP_ADJ 0set

3、prop ro.VISIBLE_APP_ADJ 1setprop ro.SECONDARY_SERVER_ADJ 2setprop ro.BACKUP_APP_ADJ 2setprop ro.HOME_APP_ADJ 4setprop ro.HIDDEN_APP_MIN_ADJ 7setprop ro.CONTENT_PROVIDER_ADJ 14setprop ro.EMPTY_APP_ADJ 15# Define the memory thresholds at which the above process classes willbe killed.# These numbers ar

4、e in pages (4k.setprop ro.FOREGROUND_APP_MEM 1536setprop ro.VISIBLE_APP_MEM 2048setprop ro.SECONDARY_SERVER_MEM 4096setprop ro.BACKUP_APP_MEM 4096setprop ro.HOME_APP_MEM 4096setprop ro.HIDDEN_APP_MEM 5120setprop ro.CONTENT_PROVIDER_MEM 5632setprop ro.EMPTY_APP_MEM 6144# Write value must be consisten

5、t with the above properties.# Note that the driver only supports 6 slots, so we have HOME_APP at the same memory level asservices.write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15write /proc/sys/vm/overcommit_memory 1write /proc/sys/vm/min_free_order_shift 4write /sys/module/lowmemoryki

6、ller/parameters/minfree 1536,2048,4096,5120,5632,6144# Set init its forked children's oom_adj.write /proc/1/oom_adj -16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30二、常見的內存使用不當的情況(

7、一)查詢數據庫沒有關閉游標 描述: 程序中經常會進行查詢數據庫的操作,但是經常會有使用完畢 Cursor 后沒有關閉的情況。 如果我們的查詢結果集比較小,對內存的消耗不容易被發(fā)現,只有在常時間大量操作的情況 下才會復現內存問題,這樣就會給以后的測試和問題排查帶來困難和風險。示例代碼:Cursor cursor = getContentResolver(.query(uri .;if (cursor.moveToNext( . . 1 2 1 2修正示例代碼:Cursor cursor = null;try cursor = getContentResol

8、ver(.query(uri .;if (cursor != null && cursor.moveToNext( . .finally if (cursor != null try cursor.close(;catch (Exception e 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8(二)構造 Adapter 時,沒有使用緩存的 convertView 描述: 以構造 ListView 的 BaseAdapter 為例,在 BaseAdapter 中提高了方法: public View getView(int posit

9、ion, View convertView, ViewGroup parent來向 ListView 提供每一個 item 所需要的 view 對象。初始時 ListView 會從 BaseAdapter 中根 據當前的屏幕布局實例化一定數量的 view 對 象 ,同 時 ListView 會將這些 view 對象緩存起來 。 當向上滾動 ListView 時,原先位于最上面的 listitem 的 view 對象會被回收,然后被用來構 造新出現的最下面的 list item 。這個構造過程就是由 getView( 方法完成的, getView(的第二個形參 View convert

10、View 就是被緩存起來的 list item 的 view 對象 ( 初始化時緩存 中沒 有 view 對 象則 convertView 是 null 。 由此 可 以 看出 , 如 果我 們 不 去使 用convertView ,而是每次都在 getView( 中重新實例化 一個 View 對象的話,即浪費資源也浪費時間,也會使得內存占用越來越大。 ListView 回收 listitem 的 view 對象的過程可以查看 :android.widget.AbsListView.Java > void addScrapView(View scrap 方法。示例代碼:publ

11、ic View getView(int position, View convertView, ViewGroup parent View view = new Xxx(.; . .return view; 1 2 3 4 1 2 3 4修正示例代碼:public View getView(int position, View convertView, ViewGroup parent View view = null;if (convertView != null view = convertView; populate(view, getItem(position; .else view

12、= new Xxx(.; .return view; 1 2 3 4 5 6 1 2 3 4 5 6(三)Bitmap 對象不在使用時調用 recycle( 釋放內存 描述: 有時我們會手工的操作 Bitmap 對象,如果一個 Bitmap 對象比較占內存,當它不在被使 用 的時候,可以調用 Bitmap.recycle( 方法回收此對象的像素所占用的內存,但這不是必須 的 , 視情況而定。 可以看一下代碼中的注釋:/* Free up the memory associated with this bitmap's pixels, a

13、nd mark the * bitmap as "dead",meaning it will throw an exception if getPixels( or * setPixels( is called, and willdraw nothing. This operation cannot be * reversed, so it should only be called if you are sure thereare no further uses for the bitmap. This is an advanced call, and normally

14、need * not be called,since the normal GC process will free up this memory when * there are no morereferences to this bitmap. */ 1 2 3 4 5 6 1 2 3 4 5 6(四)釋放對象的引用 描述: 舉兩個例子進行說明。 示例 A : 假設有如下操作public class DemoActivity extends Activity . .private Handler mHandler = . private Object

15、 obj;public void operation( obj = initObj(; .mHandler.post(new Runnable( public void run( useObj(obj; 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8我們有一個成員變量 obj ,在 operation( 中我們希望能夠將處理 obj 實例的操作 post 到 某個線程的 MessageQueue 中。在以上的代碼中,即便是 mHandler 所在的線程使用完了 obj 所引用的對象,但這個對象仍然不會被垃圾回收掉,因為 DemoActivity.obj 還保

16、有這個對象 的引用。所以如果在 DemoActivity 中不再使用這個對象了,可以在 Mark 的位置釋放對象的引用,而代碼可以修改為: public void operation( obj = initObj(; .final Object o = obj;obj = null;mHandler.post(new Runnable( public void run( useObj(o; 1 2 3 4 5 6 7 1 2 3 4 5 6 7示例 B: 假設我們希望在鎖屏界面 (LockScreen 中,監(jiān)聽系統(tǒng)中的電話服務以獲取一些信息 ( 如信號強度等 ,則可以在 LockSc

17、reen 中定義一個 PhoneStateListener 的對象,同時將它注冊到 TelephonyManager 服務中。對于 LockScreen 對象,當需要顯示鎖屏界面的時候就會創(chuàng) 建一 個 LockScreen 對象,而當鎖屏界面消失的時候 LockScreen 對象就會被釋放掉。 但是如果在釋放 LockScreen 對象的時候忘記取消我們之前注冊的 PhoneStateListener 對 象,則會導致 LockScreen 無法被垃圾回收。如果不斷的使鎖屏界面顯示和消失,則最終會 由于大量的 LockScreen 對象沒有辦法被回收而引起 OutOfMemory,

18、使得 system_process 進程 掛掉??傊斠粋€生命周期較短的對象 A ,被一個生命周期較長的對象 B 保有其引用的情況下,在 A 的生命周期結束時,要在 B 中清除掉對 A 的引用。(五)其他 Android 應用程序中最典型的需要注意釋放資源的情況是在 Activity 的生命周期中,在onPause( 、 onStop( 、 onDestroy( 方法中需要適當的釋放資源的情況。由于此情況很基礎, 在此不詳細說明,具體可以查看官方文檔對 Activity 生命周期的介紹,以明確何時應該釋放 哪些資源。三、不健壯代碼的特征及解決辦法1、盡早釋放無用對象的引用。好的辦法是

19、使用臨時變量的時候,讓引用變量在退出活動域 后,自動設置為 null,暗示垃圾收集器來收集該對象,防止發(fā)生內存泄露。 對于仍然有指針指向的實例,jvm 就不會回收該資源,因為垃圾回收會將值為 null 的對象 作為垃圾,提高 GC 回收機制效率;2、我們的程序里不可避免大量使用字符串處理,避免使用 String,應大量使用StringBuffer,每一個 String 對象都得獨立占用內存一塊區(qū)域。String str = "aaa"String str2 = "bbb"String str3 = str + str2;/假

20、如執(zhí)行此次之后 str ,str2 以后再不被調用,那它 1 2 3 4 1 2 3 4就會被放在內存中等待 Java 的 gc 去回收,程序內過多的出現這樣的情況就會報上面的那 個錯誤,建議在使用字符串時能使用 StringBuffer 就不要用 String,這樣可以省不少開 銷;3、盡量少用靜態(tài)變量,因為靜態(tài)變量是全局的,GC 不會回收的;4、避免集中創(chuàng)建對象尤其是大對象,JVM 會突然需要大量內存,這時必然會觸發(fā) GC 優(yōu)化 系統(tǒng)內存環(huán)境;顯示的聲明數組空間,而且申請數量還極大。 使用 jspsmartUpload 作文件上傳,運行過程中經常出現

21、 java.outofMemoryError 的 錯誤,檢查之后發(fā)現問題:組件里的代碼m_totalBytes = m_request.getContentLength(;m_binArray = new bytem_totalBytes;/問題原因是 totalBytes 這個變量得 1 2 1 2到的數極大,導致該數組分配了很多內存空間,而且該數組不能及時釋放。5、盡量運用對象池技術以提高系統(tǒng)性能;生命周期長的對象擁有生命周期短的對象時容易 引發(fā)內存泄漏,例如大集合對象擁有大數據量的業(yè)務對象的時候,可以考慮分塊進行處理, 然后解決一塊釋放一塊的策略。6、不要在

22、經常調用的方法中創(chuàng)建對象,尤其是忌諱在循環(huán)中創(chuàng)建對象??梢赃m當的使用 hashtable,vector 創(chuàng)建一組對象容器,然后從容器中去取那些對象,而不用每次 new 之后又丟棄。7、一般都是發(fā)生在開啟大型文件或跟數據庫一次拿了太多的數據,造成 Out Of MemoryError 的狀況,這時就大概要計算一下數據量的最大值是多少,并且設定所需最小及最大的內存空間值。四、內存泄露監(jiān)測工具 DDMS(Dalvik Debug Monitor Service:Dalvik 虛擬機調試監(jiān)控服務)這里我使用 eclipse 的 ADT 插件,并以真機為例,在模擬器中的情況類似。用

23、Heap 監(jiān)測應用進程使用內存情況的步驟如下:1. 啟動 eclipse 后,切換到 DDMS 透視圖,并確認 Devices 視圖、 Heap 視圖都是打開的。2. 將手機通過 USB 連接電腦,鏈接時需要確認手機是處于“ USB 調試”模式,而不是作 為“ Mass Storage ”。3. 鏈接成功后,在 DDMS 的 Devices 視圖中將會顯示手機設備的序列號,以及設備中正 在 運行的部分進程信息。4. 點擊選中想要監(jiān)測的進程,例訊飛輸入法 com.iflytek.inputmethod 進程。兒童短款加絨立領修身皮衣,機車風BB 出街必入休閑百搭套頭長袖衛(wèi)衣,

24、耀眼色彩搭配,酷斃了5. 明黃色寶寶衛(wèi)衣背心,夾克式設計,怎么搭到很潮來源:LETTLE MOMO 童裝淘寶網潮寶出街搶鏡帥氣搭2011年10月21日 華衣網可愛的高領卡同款打底衫,胸前立體小兔子和寶寶一起活動,絕對的拉轟哦外穿也很吸引人滴;登月最洋氣啦,所以潮寶們絕對會每人一頂飛行員帽子哦,搭配上帥氣的衛(wèi)衣,絕對是氣場范十足哦6. 點擊 Heap 視圖中的“ Cause GC ”按鈕。7. 此時在 Heap 視圖中就會看到當前選中的進程的內存使用量的詳細情況,如圖所示: 說明: a 點擊“ Cause GC ”按鈕相當于向虛擬機請求了一次 GC 操作; b 當內

25、存使用信息第一次顯示以后,無須再不斷的點擊“ Cause GC ”, Heap 視圖界面會定 時刷新,在對應用的不斷的操作過程中就可以看到內存使用的變化。如何才能知道我們的程序是否有內存泄漏的可能性呢。這里需要注意一個值: Heap 視 圖 中部有一個 Type 叫做 data object ,即數據對象,也就是我們的程序中大量存在的類類型的對象。在 data object 一行中有一列是“ Total Size ”,其值就是當前進程中所有 Java 數據對 象的內存總量,一般情況下,這個值的大小決定了是否會有內存泄漏??梢赃@樣判斷: a 不斷的操作當前應用,同時注意觀察

26、data object 的 Total Size 值; b 正常情況下 Total Size 值都會穩(wěn)定在一個有限的范圍內,也就是說由于程序中的的代碼良 好,沒有造成對象不被垃圾回收的情況,所以說雖然我們不斷的操作會不斷的生成很多對象 , 而在虛擬機不斷的進行 GC 的過程中,這些對象都被回收了,內存占用量會會落到一個穩(wěn)定 的水平; c 反之如果代碼中存在沒有釋放對象引用的情況,則 data object 的 Total Size 值在每次GC 后不會有明顯的回落,隨著操作次數的增多 Total Size 的值會越來越大,直到到達一個上限后導致進程被 kill 掉。五、內存泄露分析工具 MAT(Memory AnalyzerToolMAT 是一個 Eclipse 插件,官方下載地址: 。 (一)生成 .hprof 文件1. 打開 eclipse 并切換到 DDMS 透視圖,同時確認 Devices 、 Heap 和 Log

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論