본문 바로가기

카테고리 없음

[Android] Bitmap OutOfMemory - OOM

메모리 부족. 안드로이드에서 OutOfMemoryError라 발생하는 가장 많은 경우는 비트맵 로딩때문이다.
안드로이드는 어플리케이션 프로세스별 메모리가 제한되어 있다.(16M, 24M, 32M 등)

문제는 위의 메모리 에러가 DDMS에서 가장 쉽게 확인할 수 있는 메모리 값인 VM Heap 사이즈와는
크게 상관없이 발생한다는 것이다.
Bitmap을 로딩할 경우  VM 내의 힙메모리를 사용하는 게 아니라 VM 밖의 Native 힙메모리 영역을 사용한다고 한다.
그리고 BitmapFactory의 decode함수들은 메모리 Leak이 존재한다고 알려져 있다.

해결 방안 ::

1. 가용 메모리의 확인
 – 아래 API들을 활용해서 Native Heap 값을 확인할 수 있다. 
   Debug.getNativeHeapSize()
   Debug.getNativeHeapFreeSize()
   Debug.getNativeHeapAllocatedSize()

2. 아주 큰 이미지 파일을 불러오는 경우 BitmapFactory.Options.inSampleSize 설정을 통해 축소해서 메모리에 로드한다. 마찬가지로 BitmapFactory.Options.inPureable = true 도 사용한다.(메모리 관리 메소드)

Bitmap bitmap;
BitmapFactory.Options option = newBitmapFactory.Options();
option.inSampleSize = 1;
option.inPurgeable = true;
option.inDither = true;
bitmap = BitmapFactory.decodeResource(mRes, mRes.getIdentifier(fileName, null,null), option);

3. 더이상 쓰지 않는 Bitmap의 경우 recycle을 호출해서 바로 가용 메모리를 늘려준다.

bitmap.recycle();
bitmap = null;
((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();

4. BitmapFactory를 사용하지 않고 이미지를 바로 불러온다.


ImageView im = new ImageView(this);
File file = newFile(“ / sdcard / default.jpg”);
Uri uri = Uri.fromFile(file);
Bitmap bm = Images.Media.getBitmap(getContentResolver(), uri);
im.setImageBitmap(bm);


5. BitmapDrawable을 사용한다.

BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.icon);
Bitmap bitmap = drawable.getBitmap();

6. 이미지의 경우 시스템이 알아서 판단해서 적합한 형식으로 로딩하는데 디폴트인 RGB8888(픽셀당 4byte)로

로딩하는 경우가 많다. 이미지를 많이 사용하는 게임등의 경우 투명 이미지는 RGB4444, 불투명 이미지는 RGB565로
충분한 경우가 많으니 BitmapFactory.Options.inPreferredConfig 설정값을 어떻게 주고 있는지 확인해 본다.

* 메모리 릭이 발생하지는 않는지 확인하는 것이 기본이다.