안드로이드 초보 개발자입니다.
안드로이드의 메모리 개념은 정말 체감상 이해하기힘들군요.
단순한 UI를 가지고 있는 어플을 개발중입니다.
activity수는 16개 남짓됩니다.
각 activity는 배경한장과 버튼 한두개 정도로 구성이 되어있습니다.
이건 간단한 UI에서도 메모리가 부족한 OOM이 나네요.
배경과 버튼은 어플리케이션의 화면에 맞게 크기조절도 해놓은거라
그리 메모리가 크지 않습니다.
게다가 혹시 그때문에 OOM이 발생하나 해서 activity에서 activity로 넘어갈때
destroy를 시켜버리고 메모리를 회수하는 함수를 실행시키도록 했습니다.
callback함수를 null로 하거나 이미지를 recycle 시키는 함수죠.
하지만 이것역시 먹히지 않습니다. 일시적인 해결책일뿐 근본적인 문제가 해결되지 않습니다.
이유를 알수 없군요 overridependingtransition으로 준 activity간의 애니메이션 때문인가 해서
애니메이션 역시 주석처리를 하고 실행시켜 봤지만 OOM이 납니다.
그래서 여기 계시는 개발자 분들께 문의드립니다.
몇가지 뇌리를 스치는 원인에 대하여 말씀을 드리자면,
UI를 구성할때 xml파일을 전혀 건들지 않은상태에서 순수 코딩으로 UI를 구성했습니다.
즉 뷰의 생성을 코드로 한겁니다.
혹시 이것이 OOM의 문제가 될수도 있다고 생각하십니까?
혹은 이미지 이외의 것이 OOM을 발생시킬수 있는 원인이 될수 있나요.
현재 상황을 말씀드리자면 6메가 짜리 글씨체를 하나 쓰기 때문에
힙메모리상태가 여유가 없을거라는 예상을 할수있지만 activity 한두개 왔다 갔다 한다고
뻗을 만한 메모리는 아니라고 생각합니다.
그리고 다른 폰에서는 정상적으로 작동하지만 갤럭시 넥서스를 가지고 테스트한 결과
계속 이런 OOM이 납니다.
레퍼런스폰 자체가 메모리가 작게잡혀있나요?
두서없는 글이 었네요.
정리하자면
1. 순수 코딩으로 구성한 UI가 OOM의 원인이 될수 있습니까?
2. 이미지를 가지고 노는부분 이외에 코딩적인 부분 때문에 OOM이 날 가능성이 있습니까?
3. 레퍼런스폰이 원래 메모리가 작은건가요?
여러분의 도움을 구합니다 ㅜㅜ.
1. 관계 없을겁니다.
2. 대부분 OOM은 비트맵때문에 일어납니다. 정말로 메모리 사이즈를 벗어나는 크기로 비트맵을 할당받았거나 프로그램에 비트맵 메모리 릭이 있는 것입니다. recycle이 OOM의 만병통치약은 아닌것이 recycle명시적으로 하지 않아도 garbage collect될 때 recycle이 일어납니다. 대용량 메모리를 할당 받는 곳이 있는지 먼저 확인하고 아니면 메모리 릭이 있는지 잘 살펴보세요.
3. 레퍼런스 폰이 삼성이나 LG폰에 비해 자바 힙 메모리사이즈가 작은 건 사실입니다.
제가 VM상에서 체크를 할때는 메모리를 회수하는 함수덕분인지 거의 모든 메모리가 회수되었습니다.
몇kb 수준의 오차정도는 나더군요.
하지만 이래저래 구글링을 해본결과 VM memory가 부족할 경우 gc가 작동이 되지만
native heap memory가 부족할때는 gc가 작동을 못해서 OOM이 난다고 하더라고요.
즉, 비트맵같은 처리를 할때는 native heap memory를 이용하는데 native heap memoty는 gc가 관찰할 수 없고,
VM이 넉넉하고 native heap이 부족한 상태에서는 gc가 작동을 하지않아서 OOM이 나는거라고 하더라구요.
혹시 native heap memory를 체크할 수 있는 방법이 있나요?
웹에 있는 정보는 전부다 재각각이고 확실하지도 않은것 같아서요..ㅜ
아시다시피 진저브레드 이전에는 비트맵의 픽셀 데이터가 native heap memory에 할당되며 이 영역은 GC대상이 아닙니다.
하지만 Bitmap 자바 오브젝트 자체는 VM heap에 할당됩니다. 따라서 Bitmap 자바 오브젝트는 GC대상이 되며 GC가 될 때(즉 finalizer에서) recycle을 하게 되어 있습니다. 하지만 gc는 unpredictable한 면이 있고 bitmap의 사이즈가 통상적으로 크기 때문에 픽셀데이터만을 free해주는 recycle을 명시적으로 호출할 필요가 있었던 것이었죠.
말씀만으로는 릭은 없어보이고 정말 메모리가 부족한 듯이 보입니다. 이러면 대책없죠. 프로그램 로직을 바꾸는 수밖에요.
DDMS의 Heap 기능이 도움이 되실겁니다. ICS부터는 비트맵도 VM힙에 잡히니 보기가 아주 편합니다.
특정 기능(예를 들어 초기화면 로딩) 후 Cause GC를 한 번 눌러주시면 현재 Heap Size와 Allocated Size를 실시간으로 보실 수 있습니다.
다만 VM Heap Size는 처음에는 16M정도로 잡혔다가 점점 커집니다. 갤넥같은 경우는 48M까지 커집니다. 이 기능을 이용하면 폰트가 문제인지 다른 문제가 있는지 좀 더 쉽게 확인하실 수 있을겁니다.
대부분 이미지입니다
xml로 리스트아이템하나에 뷰가 20개 가까이 들어가는 리스트가 있었는데도 문제가 없었죠...
제경우는 페이저 + 그리드레이아웃으로 한화면에 최소 12~15개 되는 화면이 7개 가량있어서 OOM튀어나오더군요...
이미지만 한방에 100장가까이 가져오다보니...
소프트레퍼런스 + Async로 떄워서 겨우 막을수있었습니다
폰트 용량을 보니 폰트 땜시 OOM에러가 발생하는거 같은데요
폰트가 메모리에서 제거 되기전에 다른 액티비티에서 로드가 된다면 뻗을거 같습니다.
요거 외에는 딱히 주신 정보로는 파악이 불가능하네요
DDMS의 프로파일링 기능과 디버깅 기능들을 통해서 파악이 가능하겠지만,
빠르게 확인이 가능하려면,
1. 폰트를 제거(폰트 파일 및 프로세스 자체 모두 제거)한 순수한(?) 앱으로 실행 확인
2. 이미지 자체의 용량을 현저하게 줄이거나, 다른(아무거나) 이미지를 사용하거나, 일부 이미지들을 제거해 나가면서 실행 확인
위의 두 경우를 실행 해 보면 문제 파악은 될 것 같네요.
액티비티 1~2개에서 거의 무조건 죽는다면, 앱 구성하고 테스트 하는데 그렇게 오랜 수고나 시간은 들지 않을 것 같다고 생각합니다.
물론, 해보셨다면, 믿을것은 DDMS!
1. 별 관계 없다고 생각합니다.
2. 이미지를 리사이클링 하는 작업의 위치 때문에 문제가 생겼을 수도 있습니다.
예전에 저도 이미지 작업할때 리사이클링 한다고 무조건 outOfMemory가 안뜨는게 아니더구요
재활용할 부분이 없을경우 아예 텍스쳐를 비우고 해보셔요.
3. 레퍼런스폰이면 오히려 쾌적 할 것같습니다.