직접적인 Reference를 주입해서는 안된다. 반듯이 weekRefernece를 이용해서 context를 공유 해야한다. thread와 같이 Main Thread의 범위 밖에서 작동이 된다면 MainActivity가 명시적으로 종료 되어도 해당 Context가 별도의 Thread에 남아있게 되어서 Memory Leak이 나게 된다.
Handler 누수
내용상으로는 Inner class와 동일하다. weekreference를 이용해서 instance를 생성하게 해야한다.
webview를 사용할때는 해당 view item이 destory가 완전히 되었고, 그에따른 메모리 반납이 이루어 졌는지 확인해야 한다. 그렇지 않다면 Native영역과 Others영역의 메모리가 지속 누적되는 현상이 발생 하게 된다. 이러한 현상은 layout상에 있는 webview를 call하게 되면 굉장히 높은 확률로 Leak이 발생하게 된다.
I art : Explicit concurrent mark sweep GC freed 64(14KB) AllocSpace objects, 2(72KB) LOS objects, 24% free, 4MB/5MB, paused 448us total 20.082ms:
조금더 자세하게 나누어 보면 다음과 같음
Type
대상
설명
GC_Reason
Explicit
- Concurrent : 앱스레드 중단 않는 GC (백그라운드 실행) - Alloc : 힙이 이미 가득 차서 더 이상 요청받은 메모리 할당을 할 수없어서, GC를 우선 실행 시킴 -Explicit : 앱이 명시적인 GC를 요청함. gc() 호출 - NativeAlloc : Bitmap또는 Renderscript 할당과 같은 Native 메모리 할당을 위해서 실행 되는 GC (허니비를 기점으로 Bitmap은 힙으로 위치를 변경하였다) - CollectorTransition : RAM 사양이 낮은 기기에서 앱의 프로세스 상태 일시 중지 및 인식 할 수없는 상태로 변경 할때 변환이 발생함(메모리 공간을 범프 포인터 공간으로 복사하는 작업임)(Eden 영역에서 -> Survivor 영역으로의 전환 과정으로 보임) - HomogeneousSpaceCompact : 사용가능한 공간(메모리로 보임)의 압축 기법으로 백그라운드 상태에서 RAM사용량 감소와 힙 조각 모음을 위해 처리 하는 것으로 보임 - HeapTrim : 힙트림을 마주칠 때까지 수집이 차단 - DisableMovingGc : 힙압축이 이루어지는 동안 GetPrimitiveArrayCritical이 사용 됨으로써 힙의 수집기 이동을 제한 시킴
GC_Name
concurrent mark sweep
- Concurrent mark sweep (CMS) : 이미지 공간 이외의 모든 공간을 회수하고 수집하는 완전한 힙 수집기 - Concurrent partial mark sweep : 이미지 및 zygote (app_process, 요청을 리스닝하고 요청 받은 클래스를 포크한다.)공간 이외의 공간을 전부 수집하는 수집기 - Concurrent sticky mark sweep : 마지막 GC이후로 할당된 객체만 회수 하는 세대별 수집기. 수집이 빠르고 일시 중지도 잘 안일어 남으로 자주 사용됨 -Marksweep + semispace : 공간 압축이나 힙전환시 사용되는 복사 GC
Objects_freed
freed 64
회수한 객체의 수(작은규모)
Size_freed
(14KB) AllocSpace objects, 2
GC를 통해서 회수한 바이트의 수
Large_objects_freed
2
회수한 객체의 수(큰 규모)
Large_object_size_freed
(72KB)
회수한 객체의 크기
Heap_stats
24% free, 4MB/5MB,
회수한 비율로 (라이브 객체수)/(총 힙 크기), 예를 들자면 4MB가 살아있는 개체이고 5MB가 전체 힙의 크기이다. 약 24% 1MB 정도가 비어 있는 상황이라고 보면 된다. 이 값으 전체 적으로 증가만 하고 있다면 메모리 릭이라고 생각해 봐야한다
Pause Times
paused 448us total 20.082ms
공식 문서상에는 일시 중지 횟수로 나와있으나 단위를 보면 일시 중지 시간이 맞는거 같다. 객체 수집시 나타나는 일시 중지 시간 평균 및 sum이 이 pause times으로 생각된다.
Android Memory Kill 순서
시스템
관련 서비스
memory status
Cached
현재 작동 되고 있지 않고 Background에 캐쉬 되어 있는 서비스들
lmk(Low memory killer) threshold
Previous
현재 작동 중인 서비스 직전에 사용된 서비스
critical
Home
Home 기능이라고 하는데 내용상 바탕화면의 Wall paper 정도로 보임
critical
Service
클라우드 서비스, 싱크 서비스 등 백그라운드 서비스
critical
Perceptible
조회기능, 오디오, 키보드 등 듣고 입력하는 기능 들로 보임
critical
Foreground
현재 떠있는 서비스
critical
Persistent
전화 본연의 기능 및 통신 프로톨(와이파이, 블루투스 등)
Crash ()
System
system_server
Crash (reboot)
Native
init, kswapd,netd, logd, adbd 등 native bin(exec) 프로세스
Profiler 만 사용하면 다른 툴을 쓸 필요가 없는 것으로 보인다. 단, malloc 같은 경우는 native 영역에 대한 내용을 볼 수 있는 유일한 방법으로 현재까지는 보임으로 native leak이 발생하면 쓸수 밖에 없지 않나 한다.
Android RAM의 종류
RAM 사용량 Command
adb shell dumpsys meminfo <package_name|pid> [-d]
해당 명령어는 adb connect 가 되어있다는 전제이다
-d 옵션 의미 : Dalvick 및 ART 메모리 사용량에 대한 정보가 상세히 출력된다
기본적을 KB단위로 나열된다.
개인(클림 및 더티) RAM
RAM은 특정 APP에서만 사용중인 메모리로써, 해당 메모리의 양은 특정 APP의 서비스가 프로세스 킬되었을 때 온전히 Free RAM으로 되돌려 받을 수 있는 양이다. 이중에 개인 더티 RAM은 Android 스왑을 사용하지 않기 때문에 가장 중요한 대상이 된다. 메모리 Leak을 해결 해야 하는 이유도 이부분에 있다. 개발자가 지정하는 모든 Dalvik 및 Native 힙 메모리는 더티 RAM으로 처리된다. Zygote를 사용하는 공유 RAM도 있게 되는데 이부분은 공유 더티 Ram으로 불린다.
PSS(Propotional Set Size)
PSS는 하나의 프로세스만을 바라보는 사이징 방식이 아니라, 공유되는 모든 페이지에 대한 RAM까지 포함한 계산 방식이다. 예를 들자면 프로세스 2개가 2메가를 공유하는 프로세스를 접근 하고 있다면, 1MB씩 PSS 사이즈를 분배 받게 된다. 그외 개인 더티 RAM 사이즈는 직접적으로 PSS에 추가 된다.
정리하자면 다음과 같다.
PSS Size = 프로세스1 개인 더티 RAM + 프로세스 2 개인 더티 RAM + 프로세스 3 공유 RAM 절반
PSS외에 2가지 종류가 더 있다
RSS : Resident Set Size = Private 더티 RAM + Shared RAM 전체
USS : Unique Set Size = RSS - shared RAM 전체 = Private Dirty RAM만 대상으로 함
만약에 java 가 없다면 JDK를 install하고 JAVA_HOME 을 이와 같이 설정해야 한다.
source .bash_profile
https://jdbc.postgresql.org/download.html 에서 최신 드라이버 다운
<<아무 디렉토리나>>/bin 으로 이동
jdbc driver 등록
stevenucBookPro:bin steven$ ./jboss-cli.sh You are disconnected at the moment. Type 'connect' to connect to the server or 'help'for the list of supported commands. [disconnected /] connect