Android Out of Memory (OOM)

转载 2012年11月13日 16:25:45
何謂OOM呢?
OOM (Out of Memory),就是溢存的意思,
白話點就是超出記憶體大小了,
每個APP,都會有配置一定大小的heap size,
但這個heap size在每支設備上都不同,
像在Nexus one就是24mb,HTC Sensation只有16mb,
大小都不一定的,所以我們在寫app時,
必須做好記憶體的控管,

有些人可能會納悶,不是用JAVA寫的嗎?
JAVA無法對記憶體有更進一步的操作(配置、釋放)阿,
怎麼做好記憶體的控管呢?
恩,沒有錯。

【那OOM的問題會發生在哪?】
就是在圖片的使用!!!!!!
你每調用一張圖片,在android上都會做到auto scale的動作,
在做auto scale的動作是用C去配置記憶體的,
因此就會占用記憶體,
如果沒有做好控管,就會發生溢存!
那怎麼做好控管呢?


你們有時會發現有些APP好大喔,
有部分原因可能是引用其他外部的lib,
很少是因為程式碼寫太多....
大部分的問題就是在圖片太多,且太大,
沒有好好善用draw9patch,何謂draw9patch可以來這看
當然draw9patch並不適用所有的案例,
甚至連根據dpi的不同,放圖片在不同的資料夾,
這方法我也覺得不適用所有案例,
我大多都還是去取得螢幕大小,自己去做到裁切圖片的動作,
個人覺得這樣是最精準的(畢竟android device實在太多..................)。


網路上有些解法是,
在做重新裁切或者取得圖片的動作時,
把圖片品質設小一點。
當然這也是一種解法啦。
但個人看法,認為這解法治標不治本,
怎麼說呢? 畢竟如果圖片一多,
OOM的問題還是會發生。


所以最根本的解法在於recycle!
但是recycle的時機很重要,
畢竟如果圖片還在使用中就進行recycle的話,
可是會發生crash的。

我的建議是在Android Life Cycle中的onDestroy中進行recycle,
此時最為保險。當然如果你能保證你的圖片用不到了,就可以進行recycle了。
不一定要照我的建議而做。


這裡有個情境,假設我有4個畫面,A,B,C,D。
A有按鈕跳到B
B有按鈕跳到C
C有按鈕跳到D
每個畫面都有一張不同的背景圖,
怎麼設背景圖呢?
大部分人會在layout.xml中去做設定,
或者會在程式中設定,
如下:
1 linearLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.bg_normal));
這樣看似沒有甚麼問題,
但如果ABCD畫面換來換去,經過多次換來換去以後,
這時候heapSize就會越來越小....
最後就會發生OOM!

所以較好的做法就是在lifecycle中的onCreate中,
去做init的動作,
先宣告二個全域的變數
一個是用來存圖片的BitmapDrawable
一個是放置圖片的LinearLayout,如下:
1 private LinearLayout llBackgroundPanel = null;
2 private BitmapDrawable bmpDrawImg  = null;

接著在onCreate中去呼叫一個自己寫好的函數(fnSetBackground)
這個函數就是用來設背景圖片的,如下:
1 @Override
2 public void onCreate(Bundle savedInstanceState) {
3     super.onCreate(savedInstanceState);
4     setContentView(R.layout.a);
5     fnSetBackground(); // 呼叫函數
6 }

而函數內容如下:
1 public void fnSetBackground(){
2     // 先取得LinearLayout
3     llBackgroundPanel = (LinearLayout) findViewById(R.id.llBackgroundPanelChangePwd);
4     // 取得該張圖片,並放置在變數bmpDrawImg中
5     bmpDrawImg = new BitmapDrawable(getResources().openRawResource(R.drawable.bg_normal));
6     // 最後就是設定圖片
7     llBackgroundPanel.setBackgroundDrawable(bmpDrawImg);
8 }

完成上面步驟,只是設置圖片而已,
還是無法解決OOM的問題,下面才是解決的方式,
在lifecycle中的onDestroy中去進行清空,
01 @Override
02 protected void onDestroy() {
03     super.onDestroy();
04     // 每個Drawable被加到VIEW上面都會產生一個callback,所以在recycle圖片之前,必須先把callback設成null
05     // 設成null以後,背景圖片自然就會不見,就會變成黑的背景。bmpDrawImg的狀態就會是沒有被使用中。
06     llBackgroundPanel.getBackground().setCallback(null);
07   
08     // 先判斷bmpDrawImg 是否為null,如果不是null,且bmpDrawImg 還沒有被recycle的話就進行recycle
09     if (null != bmpDrawImg && !bmpDrawImg.getBitmap().isRecycled()){
10         bmpDrawImg.getBitmap().recycle();
11     }
12     System.gc();
13 }


照著上面的方法實作就能避免掉OOM的問題,
我寫在destroy的原因在於,
android lifecycle的特性,
當你A按下按鈕到B,
這時候在B畫面中按下返回按鈕(back),
是不是就回到A了呢?
第一次按下返回按鈕,B會去調用onDestroy這個method,
如果這時候沒有進行recycle,那麼那塊記憶體空間就不會被釋放,
就會被占用著....
如果沒有進行RECYCLE,
久而久之,你持續返回A,又跳到B,重複著這動作好幾次,
圖片就被產生好幾次,
很快就會發生OOM,至於多快,就視你的圖片大小瞜!

论 内核 OOM(out of memery) 引发的 程序被 killed

一、 描述  自己的代码 ,在平时环境中跑着没有问题的,但是today 测试在跑压力的时候 发现程序跑个 5min 左右就自己断了,程序没有产生core文件,而是显示的 是 killed ? 二、...
  • vevenlcf
  • vevenlcf
  • 2015年12月03日 09:44
  • 1371

Linux Out-Of-Memory(OOM) Killer分析

Linux Out-of-Memory(OOM) Killer       Linux有一个特性:OOM Killer,一个保护机制,用于避免在内存不足的时候不至于出现严重问题,把一些无关的进程优...
  • chenleixing
  • chenleixing
  • 2015年07月27日 08:53
  • 1718

彻底解决Android 拍照 内存溢出 Out of Memory的问题

内存溢出相信做过编程的人都知道一二,这里说Android 内存溢出的问题:、问题描述:Android下的相机在独自使用时,拍照没有问题,通过我们的代码调用时,也正常,但是更换了不同厂商的平板,ROM由...
  • cctcc
  • cctcc
  • 2014年10月15日 21:29
  • 11166

android out of memory(OOM)

一. 1.什么是 OutOfMemoryError: 官方引用: Thrown when a request for memory is made that can not be sa...
  • gongsunjinqian
  • gongsunjinqian
  • 2014年11月17日 17:35
  • 494

插拔串口,linux系统提示OOM异常,提示内存用尽Out of memory: Kill process

插拔串口serial,linux系统提示OOM异常,提示内存用尽并杀死进程的问题。SysRq : Manual OOM execution Out of memory: Kill process...
  • gujintong1110
  • gujintong1110
  • 2016年11月18日 17:27
  • 663

Android内存溢出整理总结 OOM(Out Of Memory) 加载的图片太多或图片过大时经常出现OOM问题

Android内存溢出整理总结 OOM(Out Of Memory) 加载的图片太多或图片过大时经常出现OOM问题加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,整理下: ...
  • west8623
  • west8623
  • 2016年03月03日 14:40
  • 1478

一个oom(out of memory)问题的定位和“”解决“”

先说下背景:          主调模块有n台机器, 被调模块有6台机器(均衡地提供服务), 他们之间是网络调用。 而且, 被调模块在收到主调模块的网络包后, 先立即回一个响应给主调模块, 然后做自己...
  • stpeace
  • stpeace
  • 2017年03月23日 23:43
  • 2872

Out of memory, OOM killer输出信息分析

当out of memory发生时,out_of_memory函数会选择一个内核认为犯有分配过多内存 “罪行”的进程,并杀死该进程。这就有很大的几率腾出较多的空闲页,然后再跳转回重试内存分配的操作。 ...
  • kickxxx
  • kickxxx
  • 2015年12月17日 10:42
  • 7691

由一个stack OOM引发的血案

近期在App监测平台上发现如下错误信息:java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try ...
  • oscaryue
  • oscaryue
  • 2017年06月09日 18:02
  • 3430

android out of memory oom问题

基于Android开发应用时,可能会挺时常出现Out Of Memory 异常.   在Android中,一个Process 只能使用16M内存,要是超过了这个限定就会跳出这个异常。这样就要求我...
  • nickDeLove
  • nickDeLove
  • 2012年07月26日 10:43
  • 835
收藏助手
不良信息举报
您举报文章:Android Out of Memory (OOM)
举报原因:
原因补充:

(最多只允许输入30个字)