본문 바로가기
Android/Android관련 이것 저것..

OOM Killer ,LMK

by 봄석 2019. 9. 10.

OOM Killer ,Low Memory Killer

 

OOM Killer와 LOM Killer에 대하여 알아보고 , 어떤것이 더 안드로이드 환경에 적합한지도 알아보도록 하겠습니다.

 

OOM Killer

- linux kernel의 메모리 부족시 메모리 확보를 하는 process
- src 
위치 : mm/oom_kill.c

시스템 구동중 메모리가 부족하면 운영체제 내부의 우선순위 알고리즘에 의해 프로세스를 죽입니다.
리눅스 커널은 프로세스의 메모리 할당시 남은 메모리가 없는 상황을 처리하기 위해 OOM(Out of Memory) Killer 를 가지고 있습니다.
그 것은 모든 프로세스를 어떤 제약으로 점수를 매겨 init을 제외한 최고 점수의 프로세스는 죽여 메모리를 확보한다.
따라서 일반적으로 서버를 운영할때에는 서비스데몬이 oom-killer에게 안죽도록 메모리관리를 잘해야 합니다.

 

 

그럼 OOM의 발생원인은 ??

1. Java Heap에서 OOM이 발생하는 이유

  • Java Heap의 크기가 작은 경우
    • Heap의 크기가 256M인 상황에서  300M의 크기의 객체를 생성할 때  등
  • Memory Leak이 발생하는 경우
    • 메모리 누수가 발생하여 HEAP에서 지워지지 않는 객체들이 좀비처럼 계속 남게될때
  • finalize 메소드에 의한 Collection 지연
    • 특정 Class에 finalize 메소드가 정의되어 있는 경우, 이 Class Type의 Object는 GarbageCollection 발생시 즉각적으로 Collection 되지 않습니다. 대신 Finalization Queue에 들어간 후Finalizer에 의해 정리가 되게됩니다.. Finalizer는 Object의 finalize 메소드를 실행한 후 메모리 정리 작업을수행합니다. 만일 finalize 메소드를 수행하는데 오랜 시간이 걸린다면 그 만큼 객체가 오랫동안 메모리를 점유하게 됩니다. 이로인해 OOME가 발생할 확률이 높아집니다.

 

2. Permanent Space ( Meta Space)에서의 OOM 발생 이유

  • Permanent Space는 Class의 메타 정보를 저장하는 공간입니다
  • 따라서 많은 수의 Class를 로딩하는Application의 경우 Permanent Space의 크기가 작으면 OOME가 발생할 수 있습니다. 다음과 같은 유형의Application들에서는 Permanent Space의 크기를 키워줄 필요가 있습니다.

    2-1. class Loading 과  OOM

    Class Reloading이란 Runtime에Class가 재생성되면 이를 JVM을 Reboot하지 않고 Reloading하는 기능을 의미합니다. 

    Class Reloading이자주 발생하면 Permanent Space가 금방 꽉차게 되고 OOME가 발생하게 됩니다.

 

 

3. Native Heap에서의 OOM

Java Heap과 Permanent Space가 Java와 관련된 Object들이 거주하는 공간인 반면, 

NativeHeap은 OS 레벨의 Native Object나 JNI Library 레벨의 Native Object이 거주하는 공간이다.

 

Native Heap에서 메모리 부족이 발생하는 이유는 매우 다양합니다.

 

  • Thread Stack Space가 부족한 경우
  • Virtual Space Address가 소진된 경우
  • Swap Space가 모자란 경우
  • JNI Library에서 Memory Leak이 발생하는 경우
  • Thread Stack Space와 OOME

Native Heap에서 OOM이 발생히 JVM은 심각한 상황이라고 판단, fatal error를 발생시킵니다.

 

 

 

 Low Memory Killer ( LMK)
- 
안드로이드에 특화된 OOM
- src
위치 : /drivers/staging/android/lowmemorykiller.c

(공식 커널에선 제외되어 안드로이드 커널에서만 볼 수 있다.)

 

리눅스 커널의 기본 메모리 정책은 OOM Killer로 대표되는데 메모리가 부족한 상황에서 최대한의 가용성을 확보하기 위해 가상 메모리를 가장 많이 할당한 프로세스를 죽이는 형태로 되어 잇습니다.
이런 정책은 서버나 임베디드 환경에서 주요 서비스나 주요 어플리케이션을 죽일 수 있습니다.
안드로이드의 가용 RAM이 설정된 Threshold 이하로 떨어지게 되면 프로세스 중요성별로 분류된 6가지 그룹중 해당 Application Kill 하도록 설정되어 있습니다.
그래서 시스템을 최종 사용자(end user) 관점에서 안정적이게 만듭니다.

 

 

 

**LMK 동작 절차 

어플리케이션은 자신의 상태(adj)를 항상 가지고 있는다.

(/proc/<pid>/oom_adj) 6개의 메모리 임계값(minfree)으로 단계별로 메모리 문제를 다룬다.

어플리케이션의 상태 변화를 인지하여 어플리케이션 상태를 수정한다. adj과 minfree 값은 짝을 이룬다.

(529, 24576) (1000, 30720) minfree값 이하로 메모리가 남은 경우 adj 값 이상의 어플리케이션을 제거한다.

adj 값이 높을 수록 먼저 제거되고 다음 단계는 가상 메모리 양을 비교한다.

 

 

 

그렇다면 안드로이드는 OOM과 LOM 중 무었을 ??

OOM Killer는 주요 application을 죽일수도 있습니다. 주요한 어플리케이션이 죽지않는다는 보장을 할수 없다는 것은 

안드로이드에 맞지 않음을 뜻합니다.

 

반면에 LMK은 

 process에게 adj값을 부여하여, memory가 minfree 이하로 떨어질 경우 높은 adj값을 가진 process를 kill하여 memory 확보합니다.

(  - /kernel/drivers/staging/android/lowmemorykiller.c)

Android는 가용 메모리가 설정된 6개의 임계치(minfree) 이하로 떨어지면 해당 그룹 별로 프로세스를 죽이도록 설정되어 있습니다.

 

 

 

결론을 정리하면 사실 안드로이드는   OOM  Killer 와  LMK를 모두 사용합니다 .

즉, LMK는 OOM killer 동작 전에 여유 메모리를 확보하는 안드로이드에서 추가된 모듈이다


 

참고  - http://blog.nuriware.com/archives/557

         - https://dreamlog.tistory.com/307 [꿈꾸는 사람.]

         - http://egloos.zum.com/shadowxx/v/10781292

댓글