Android OOM與 leak window

來源:互聯網
上載者:User

OOM是Android  Out  Of   Memory的縮寫,基於Android開發應用時,可能經常出現Out Of Memory
異常.
在Android中,一個Process 只能使用16M記憶體,要是超過了這個限定就會跳出這個異常。這樣就要求我們要時刻想著開釋資源。Java的回收工作是交給GC的,如何讓GC能即時的回收已經不用的對象,有許多辦法。

  因為總記憶體的施用超過16M而引起OOM的情況,非常簡單,我就不繼續展開說。值當注意的是Bitmap在不用時,肯定是要recycle,不然OOM是非常容易出現的。


  但是還會出現另外一種情況:明明還有許多記憶體,但是發生OOM了。

  這類情況時常出現在產生Bitmap的時候。有興趣的可以試一下,在一個函數裡產生一個13m 的int數組。

  再該函數結束後,按理說這個int數組應該已經被開釋了,或者說可以開釋,這個13M的空間應該可以空出來,

  這個時候要是你繼續生白手起家的百萬富翁成一個10M的int數組是沒有問題的,反而產生一個4M的Bitmap就會跳出OOM。這個就奇怪了,為啥子10M的int夠空間,反而4M的Bitmap不敷呢? 

  這個問題困擾好久,在網上,國外各大論壇搜颳了好久,一般關於OOM的解釋和解決方案都是,如何讓GC儘快回收的代碼風格之類,並沒有現實的支出上面所說的情況的根源。


  直到昨天在一個老外的blog上終於看到了這方面的解釋,我理解後歸納如下:

  在Android中:

  1.一個進程的記憶體可以由2個部門組成:java 施用記憶體 ,C 施用記憶體 ,這兩個記憶體的和必需小於16M,不然就會出現各人熟悉的OOM,這個就是熬頭種OOM的情況。


  2.越發奇怪的是這個:一朝記憶體配置給Java後,以後這塊記憶體縱然開釋後,也只能給Java的施用,這個估計跟java虛擬機器裡把記憶體分成好幾塊進行緩衝的原因有關,反正C就別想用到這塊的記憶體了,所以要是Java突然佔用了一個大塊記憶體,縱然很快開釋了:


  C能施用的記憶體 = 16M - Java某一瞬間佔在校大學生創業點子用的最大記憶體。

  而Bitmap的產生是路程經過過程malloc進行記憶體配置的,佔用的是C的記憶體,這個也就說明了,上面所說的的4MBitmap無法產生的原因,因為在13M被Java用過後,剩下C能用的只有3M了。


leak window    按字面瞭解大概就是說一個表單泄漏了,也就是我們常說的記憶體流失,為什麼表單會泄漏呢?

02-29 10:07:51.410: ERROR/WindowManager(4236): Activity cn.bookall.android.zbook.reader.DocReader has leaked window android.widget.TextView@485348b0 that was originally added here
02-29 10:07:51.410: ERROR/WindowManager(4236): android.view.WindowLeaked: Activity cn.bookall.android.zbook.reader.DocReader has leaked window android.widget.TextView@485348b0 that was originally added here
02-29 10:07:51.410: ERROR/WindowManager(4236):     at android.view.ViewRoot.<init>(ViewRoot.java:247)
...

02-29 10:07:51.410: ERROR/WindowManager(4236):     at cn.bookall.android.zbook.reader.DocView.ShowPopWindowCenter(DocView.java:506)

...

02-29 10:07:51.600: ERROR/AndroidRuntime(4236): java.lang.IllegalArgumentException:View not attached to window manager

產生原因:
我們知道Android的每一個Activity都有個WindowManager表單管理器,同樣,構建在某個Activity之上的對話方塊、PopupWindow也有相應的WindowManager表單管理器。因為對話方塊、PopupWindown不能脫離Activity而單獨存在著,所以當某個Dialog或者某個PopupWindow正在顯示的時候我們去finish()了承載該Dialog(或PopupWindow)的Activity時,就會拋Window
Leaked異常了,因為這個Dialog(或PopupWindow)的WindowManager已經沒有誰可以附屬了,所以它的表單管理器已經泄漏了。
解決方案:
關閉(finish)某個Activity前,要確保附屬在上面的Dialog或PopupWindow已經關閉(dismiss)了。

       @Override 
      public void onPause(){
         super.onPause();
         if(pw != null) {
              pw.dismiss(); 
         }
      }

相關文章

聯繫我們

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