在Android 專案時的防止Memory leak 要注意的事項
http://www.oschina.net/question/54100_32632
一般來說,Java VM是會有Gargage Collect的。但是如果object在其他的object 有reference的話,那VM是不會做cleanup的。
常見的例子是在Activity 上發生。
因為在a) 由一個activity 跳到另一個activity 或是b)在screen rotation 時,Android 系統會新建一個新的Activity,而原先的Activity 會被釋放,最後會被Gargage Collect.。但如果其他的Class 有用上這個Activity ,這個activity 就不會被Gargage Collect,因而引起memory leak 的問題。
例子
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
31
32
33
34
35
36
|
public
class
MyActivity extends
Activity{ public
void
onCreate(Bundle icicle){ super .onCreate(icicle); Utility.registerCallback( this ); } } public
class
Utility { private
static
Classback m_callback = new
Callback(); public
static
void
registerCallback(Context c){ m_callback.registerCallback(c); } } public
class
Callback { private
context m_context; public
void
registerCallback(Context c){ m_context=c; } public
void
unregisterCallback(Context c){ if
( c == m_context ){ m_context= null ; } } } |
在以上的例子中,因為class Callback 中的m_context 把 MyActivity 抓著了。 所以在這個Activity完成後,Garage Collect是不可以釋放MyActivity 的。
一個解決方案是在Activity離開前,釋放在外面的reference。
例子
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
public
class
MyActivity extends
Activity{ public
void
onCreate(Bundle icicle){ super .onCreate(icicle); Utility.registerCallback( this ); } public
void
onDestroy() { super .onDestroy(); Utility.unregisterCallback( this ); } } public
class
Utility { private
static
Classback m_callback = new
Callback(); public
static
void
registerCallback(Context c){ m_callback.registerCallback(c); } public
static
void
unregisterCallback(Context c){ m_callback.unregisterCallback(c); } } public
class
Callback { private
context m_context; public
void
registerCallback(Context c){ m_context=c; } public
void
unregisterCallback(Context c){ if
( c == m_context ){ m_context= null ; } } } |
其他的相關事項
1)在SDK中的DigitalClock Widget ,因為DigitalClock要註冊一個observer,所以會用把載上DigitalClock widget的Activity作為那個observer。但在SDK的DigitalClock是有一個Bug的,因為在DigitalClock 的onDetachedFromWindow中是沒有unregister 那個observer的。 解決方法是自己寫一個DigitalClock。詳情請看附上的程式碼(DigitalClockNew.java)。
2)在SDK中的Toast的function makeText 是要求傳一個Context的,但在Toast的程式碼中,這個Context是會用做callback上。如果是傳Activity作為那個 Context的話,那會發生memory leak的問題。解決方法是傳 Application Context,而不是ActivityContext。
如何檢視Memory leak的問題
如果懷疑有memory leak的問題,可先執行那個apk在emulator上,然後在PC上執行adb shell,,然後執行ps,檢視你的process 的pid。
在apk上執行有memory leak可疑的動作後,可以做下面的診斷
1. 執行 dumpsys meminfo <pid>
這個指令顯示pid的memory資料。注意是 Activity的 數量,如果數量是不斷上升,那就是有memory leak。 注意,因為在未執行Gargage Collect前,Activity是不會被釋放的。可以在DDMS上執行手動的Gargage Collect。
2. 把process 的memory dump 出來,看memory leak的所在
先執行 chmod 777 /data/misc,然後執行 kill -10 <pid> ,在 /data/misc 上會看到那個pid 的memory leak,(如heap-dump-tm1265266619-pid1673.hprof )
用adb pull ( 如adb pull /data/misc/ heap-dump-tm1265266619-pid1673.hprof 1673.hprof )把這個檔案拷回電腦上。
然後,用在PC上執行hprof-conv (如hprof-conv 1673.hprof 1673_a.hprof) 把那個拷回來的hprof轉換成 Eclipse Memory Tool 可以支援的格式。
用Eclipse Memory Tool (http://www.eclipse.org/mat/), 開啟轉換了的memory dump。 在Eclipse Memory Tool 上,按OQL,輸入 “select * from instanceof android.app.Activity” , 這個指令可以找所以在系統上是android.app.Activity 的 instance。(詳見下圖)
如果在object的旁帶有“Unknown”的話,那object是可以被Gargage Collect的。要看其他的object是什麼原因不可以被Gargage Collect 的話,可以在那個object上right-click,然後選Path to GC Roots, exclude weak/soft reference 。 (weak 和soft reference 都是可以被VM查到的,所以是可以Gargage Collect的。)
在Path to GC Roots 中,可以看到WidgetManagerHome 是因為Toast中的inner class TN 把 這個WidgetManagerHome抓住了。
相關文章
- Android memory leak using MATAndroid
- 如何理解Memory leak
- vite構建專案步驟以及所遇到的坑,要注意的事項Vite
- for in 迴圈遍歷物件時需要注意的事項物件
- 在專案中的更換 React Hooks 注意事項ReactHook
- Android WebView Memory Leak WebView記憶體洩漏AndroidWebView記憶體
- Android: Unknown “Bitmap” cause by 'mGlow' causing memory leakAndroid
- 部署專案注意事項
- fgets讀取檔案時的注意事項
- OA系統在選型時的注意事項
- Oracle DBLink bug引發的故障(Session Hang Memory leak)OracleSession
- phpstudy 的安裝後需要注意事項PHP
- 網站定製開發需要注意的事項網站
- Linux C/C++ Memory Leak Detection ToolLinuxC++
- Python面試中需要注意的幾點事項!Python面試
- 選擇物聯網路卡需要注意的事項
- 拼多多商家入駐平臺要注意的事項
- visual studio建立專案時需要注意的問題
- Laravel 專案上線的一些注意事項Laravel
- 專案經理之專案經理注意事項
- 移動遊戲進入海外市場時需要注意的六大事項遊戲
- 企業訂立ERP軟體合同時需要注意的七個事項(轉)
- 在T-SQL中使用臨時表的注意事項SQL
- Roll-out 專案注意事項
- 專案經理注意事項(轉)
- PG 資料庫 DTS 遷移需要注意的事項:資料庫
- Oracle 10g rac升級需要注意的事項Oracle 10g
- 資料所有權設定中需要注意的事項
- 測試在專案流程中的那些事兒
- 什麼是工時管理系統?企業使用時需要注意哪些事項
- 用Unity做個遊戲(一) - 建立專案時需要注意的點Unity遊戲
- 用IDA匯出map檔案時的注意事項
- 軟體開發中專案管理的注意事項(轉)專案管理
- 在網頁中插入xml+flash時的注意事項【Z】網頁XML
- 【YEP】專案Oracle考卷使用注意事項Oracle
- SSL證書續簽的話有哪些事項需要注意
- 複製資料庫中需要注意的幾點事項資料庫
- 寫技術類Blog需要注意的幾個事項