Java Virtual Machine (JVM)과 메모리 관리
C 나 C++ 에서는 OS 레벨의 메모리에 직접 접근하기 때문에 free() 라는 메소드를 호출하여 할당받았던 메모리를 명시적으로 해제해주어야 한다. 그렇지 않으면 memory leak 이 발생하게 되고, 현재 실행중인 프로그램에서 memory leak 이 발생하면 다른 프로그램에도 영향을 끼칠 수 있습니다.
반면, 자바는 OS 의 메모리 영역에 직접적으로 접근하지 않고 JVM 이라는 가상머신을 이용해서 간접적으로 접근한다. JVM 은 C 로 쓰여진 또 다른 프로그램인데, 오브젝트가 필요해지지 않는 시점에서 알아서 free() 를 수행하여 메모리를 확보한다. 웹 애플리케이션을 만들 때 모든 것을 다 직접 개발하여 쓰기보다 검증된 라이브러리나 프레임워크를 이용하는 것이 더 안전하고 편리한 것 처럼, 메모리 관리라는 까다로운 부분을 자바 가상머신에 모두 맡겨버리는 것이다.
프로그램 실행시 JVM 옵션을 주어서 OS에 요청한 사이즈 만큼의 메모리를 할당 받아서 실행하게된다. 할당받은 이상의 메모리를 사용하게 되면 에러가 나면서 자동으로 프로그램이 종료된다. 그러므로 현재 프로세스에서 메모리 누수가 발생하더라도 현재 실행중인 것만 죽고, 다른 것에는 영향을 주지 않는다.
이렇게 자바는 가상머신을 사용함으로써 (운영체제로 부터 독립적이라는 장점 외에도) OS 레벨에서의 memory leak 은 불가능하게 된다는 장점이 있다.
자바가 메모리 누수현상을 방지하는 또 다른 방법이 가비지 컬렉션이다.
메모리릭 (메모리 누수)이란?
- 앱을 개발할 떄는 제한된 메모리를 어떻게 사용해야 좋은 성능을 낼 수 있는지 항상 고민해야한다. GC을 통해 알아서 메모리를 관리해 주지만 능사는 아니다. 아무리 관리를 해준다 해도 개발자가 신경을 쓰지 않으면 메모리릭과 ORM이 발생하기 마련이다.
- 사용이 끝난 메모리를 반환하지 않은 경우 메모리 릭이 발생한다. 이렇게 사용하지 않은 메모리 양이 계속 증가하게 되면 최악의 경우 ORM를 발생시키고 앱이 강제 종료되면서 할당되었던 메모리가 시스템으로 회수된다.
메모리 누수는 어떤 이유에서든 지간에, 운영체제 또는 사용가능한 메모리 풀에서 반환되지 않으면서 동시에 애플리케이션에서 더이상 필요로 하지 않는 메모리로 정의 될 수 있다. 프로그래밍 언어는 메모리 관리를 각각 다른 방법으로 처리한다. 이런 방법들은 메모리 누수를 이르킬 확률을 감소시킨다. 그러나 어떠한 메모리가 돌아 오지 않는지는 시스템이 결정할 수 없는 문제다. 즉, 오직 개발자만이 메모리의 일부를 운영제체에 반환할 수 있는지 여부를 명확히 알 수 있다. 어떤 프로그래밍 언어에서는 개발자들이 이 것을 하는데 도움을 주는 기능을 제공한다. 다른 언어에서는 개발자들이 메모리가 사용되지 않을 때를 완전히 명시하는 것을 기대하는 언어도 있다.
- 메모리 릭의 원인은 무엇일까?
- 정적(Static) view/context/activity 사용
- Register와 unregister listeners
- Non-Static inner class
- getContext()와 getApplicationContext()의 잘못된 사용
- 일반적인 메모리 누수는, 모든 연관 참조가 범위(일반적으로 메서드 완료나 객체의 소멸)를 벗어나기 전에 할당한 메모리를 해제하지 않는 경우에 발생한다. 일반적인 메모리 누수와 다르게, 논리적인 메모리 누수는 앱에서 더는 필요 없는 객체의 참조를 해제하지 않은 것의 결과이다. 객체에 강한 참조(strong reference)가 있는 경우에, 가비지 컬렉터는 메모리에서 객체를 제거할 수 없다. 만약 한 컨텍스트(Context)에서 누수가 발생한다면 안드로이드 개발에 특히 문제가 된다. 액티비티(Activites)와 같은 컨텍스트는 많은 양의 메모리에 많은 참조(예로, 뷰 계층과 기타 자원 등)를 가지고 있기 때문이다. 컨텍스트가 누수된 경우, 컨텍스트가 가르키는 모든 것들 또한 누수된다. 대부분 안드로이드는 제한된 메모리를 사용하는 모바일 기기에서 실행해서, 누수가 많이 발생하면 앱에서 사용할 가용메모리가 전부 소진될 가능성이 매우 크다.
ANR 이란?
- Application Not Responding(애플리케이션 응답 없음) 오류
- 원인은?
- 메인스레드(UI 스레드)가 너무 오랫동안 차단되었을 때 발생
- UI가 있는 input 이벤트에 5초안에 반응하지 않을 때
- UI가 없는 포그라운드에 10초안에 활동이 없을 때
- BroadcastReceiver가 상당한 시간 내에 실행을 완료하지 못했을 때
- 메인스레드(UI 스레드)가 너무 오랫동안 차단되었을 때 발생
- ANR 예방하려면?
- 시간 소모가 많은 작업은 스레드를 통해 처리
- 사용자에게 프로그레스바 등을 이용해 작업의 진행과정을 알려 기다리도록 한다.
LMK 란?
- Low Memory Killer 오류
- 안드로이드에서 가용 메모리(available memory)가 부족할 때 프로세스들을 죽이는 동작
- Linux Kernel의 OOM Killer가 안드로이드의 주요 서비스나 어플리케이션을 죽일 수 있는 문제를 보완하기 위해, 가용 메모리가 설정된 6개의 임계치(minifree) 이하로 떨어지면 해당 그룹 별로 프로세스를 죽이도록 설정한 기능으로 OOM 전에 여유 메모리를 확보하기 위한 안드로이드에서 추가된 모듈
- LMK의 목적
- LMK의 목적은 바로 가용 메모리를 확보하는 것이다. 이것이 부족하면, PC나 휴대폰 등과 같은 시스템들의 성능이 크게 떨어집니다. 무지무지 느려지는 거죠. 심하면 앱 하나 띄우는데 몇 초 이상의 시간이 걸릴 수도 있습니다. 이런 문제를 방지하기 위해서 안드로이드는 사용하지 않는 프로세스들을 메모리에서 지워야 합니다. 여러분들이 가지고 계시는 안드로이드 폰들에서 LMK가 바로 이러한 역할을 수행하고 있습니다.
- LMK 의 Priority
- LMK 는 우선순위를 가지며 우선순위가 낮은 경우 부터 메모리에서 해제된다. (아래로 갈수록 우선순위가 낮다)
- foreground process(현재 포그라운드에 올라온 애플리케이션, 현재 동작하고 있는 서비스)
- visible process(사용자가 화면에서 볼 수 있지만 포그라운드가 아닌 경우 ex. 다이얼로그 에 가려진 onPause 상황 )
- service process (직접 화면에 보이지는 않지만, 백그라운드에서 동작하는 데이터 업로드 또는 다운로드 경우, 오랫동안 동작한 서비스)
- cached process (현재 사용하지는 않지만, 메모리에 적재되어 있는 프로그램)
OOM 이란?
- Out Of Memory 오류
- 안드로이드는 먼저 LMK 로 진행하다가, 더 이상 내릴 프로그램이 없을 때 OOM 순서를 밟는다
- 프로그램이나 운영체제에서 사용할 메모리를 할당하지 못하는 컴퓨터 동작 상태입니다. 리눅스는 MMU(Memory Management Unit)이란 하드웨어를 이용하여 가상 메모리를 물리 메모리로 변환하여 사용하는데, 가상 메모리로 사용하기 때문에 물리 메모리보다 더 큰 메모리를 사용할 때 OOM이 발생합니다.
메모리 릭 찾는 방법
메모리 프로파일러를 사용하여 앱의 메모리 사용량 검사
developer.android.com/studio/profile/memory-profiler?hl=ko
아래 글 꼭 시간내서 정독하기
!!!!!!!!!!!!!!!!!
yaboong.github.io/java/2018/06/09/java-garbage-collection/
참고
dzone.com/articles/java-memory-management
yceffort.kr/2020/07/memory-leaks-in-javascript
yaboong.github.io/java/2018/06/09/java-garbage-collection/
https://www.guru99.com/java-virtual-machine-jvm.html
'Language > Java' 카테고리의 다른 글
Java 컬렉션(Collection) (0) | 2021.04.22 |
---|---|
Java 자료형 (0) | 2021.04.22 |
POJO, DAO, DTO, VO 차이 (0) | 2021.04.22 |
자바 가상머신 (JVM: Java Virtual Machine) (0) | 2021.04.20 |
1. BinaryGap : Find longest sequence of zeros in binary representation of an integer. (0) | 2021.04.16 |