Eclipse Memory Analyzer를 사용하여 메모리 누수 파악하기.
Java 프로세스를 다루는 Linux서버를 운영하다 보면 종종 OutOfMemory(OOM)에러를 만날 때가 있어요.
보통 OOM에러가 발생하면 시스템 자원이 소멸되어 "bash fork retry no child process" 에러로 이어지더군요.
그래서 아래와 같은 쉘 스크립트 코드를 추가하여 Java 프로세스를 실행시키더라도 "bash fork retry no child process" 에러가 발생 했을 시점엔 사용 가능한 시스템 자원이 충분하지 않아서 JVM(Java Virtual Machine)에서 덤프 파일을 생성하는 데 실패했어요.
그래서 제가 찾은 방법은 OutOfMemory(OOM)에러가 발생하기 전 힙 덤프 파일을 생성하여 메모리 누수가 되는 부분을 찾아 예방하는 방법외엔 없더라구요.
그래서 Eclipse Memory Analyzer라는 툴을 설치하고, 사용하는 방법에 대해 설명해보려 합니다.
설치
먼저 https://www.eclipse.org/mat/downloads.php 에 접속하여 개발 환경에 맞는 버전으로 설치하시면 됩니다.
(저는 윈도우 환경에서 개발하기 때문에 윈도우 환경에서 설치하였습니다.)
그 후 Zip파일로 다운받아지게 되고, 압축을 풀면 아래와 같은 파일들이 나오게 됩니다.
실행
여기에서 MemoryAnalyzer.exe를 실행한 뒤 화면 하단에 보이는 Open a Heap Dump 부분을 클릭해줍니다.
아직 프로세스에 대한 힙 덤프 파일을 생성하지 않았으므로 서버에 접속하여 힙 덤프 파일을 생성해봅시다.
힙 덤프 파일이 생성될 디렉토리로 이동 후 아래의 명령어를 입력해 주시면 자동으로 생성됩니다.
jmap -dump:format=b,file=<파일이름>.hprof <PID>
그 후 윈도우 환경으로 옮겨주기 위해 FTP 툴을 사용하여 옮겨 줍니다.
그 후 Eclipse Memory Analyzer 화면을 열어주시고, 생성한 힙 덤프 파일 디렉토리로 이동 한 뒤, 파일을 열어 줍니다.
그럼 아래와 같은 화면이 뜰텐데 어떤 레포트를 볼거냐는 부분입니다. 누수 리포트(Leak Suspects Report)를 선택해주고 Finish를 클릭해주면
이런 화면을 볼 수 있습니다.
메모리 분석
맨 위 그래프는 어떤 부분이 주로 차지 하고 있는지를 나타내고 있는 부분입니다.
그 밑에 Problem Suspect부분은 메모리 누수의 유력한 용의자를 나타내주는 부분이고,
keywords는 어떤 부분을 처리하다 발생한 건지 알려줍니다.
특히 Keywords부분에서 자신이 쓴 코드가 메모리 누수를 일으키고 있다면, 해당 코드의 위치까지 나타내줍니다.
조금 하단으로 내리게 되면
Biggest Instances라는 항목이 나오는데 어떤 항목이 힙 메모리를 가장 많이 차지하는지 보여주는 부분이에요.
여기서 눈여겨봐야 할 부분이 'Retained Heap' 부분과 'Shallow Heap'인데요.
Shallow Heap은 해당 객체가 차지하는 직접 할당된 메모리의 크기를 의미하고, Retained Heap은 특정 객체 및 해당 객체에 의해 유지되는 메모리 양을 나타내죠.
만약 어떤 인스턴스의 Retained Heap값이 Shallow Heap값보다 높은 경우 해당 객체가 참조하고 있는 다른 객체들의 메모리 사용량이 해당 객체의 직접적인 메모리 사용량보다 크다는 것을 의미하는데 이러한 경우, 해당 객체를 가비지 컬렉션해도 다른 객체들과의 연결 때문에 메모리에서 해제되지 않고 유지될 수 있어 메모리 누수의 원인이 되죠.
반대로 어떤 인스턴스의 Retained Heap 값이 Shallow Heap 값보다 낮은 경우는 일반적인 상황인데 해당 객체가 직접적으로 참조하는 다른 객체들의 메모리 사용량이 해당 객체 자체의 메모리 사용량보다 작다는 것을 의미하죠.
그래서 해당 객체가 다른 객체들에 대한 간접적인 참조를 유지하지 않거나, 해당 객체와 직접적으로 연관된 다른 객체들의 메모리 사용이 상대적으로 적은 경우로 객체의 메모리 사용이 비교적 효율적이며, 객체 그 자체의 메모리 사용량을 최적화할 수 있을 가능성이 높다는 것을 알 수 있죠.