회사에서 신규 API를 개발한 뒤 테스트를 진행하면서 memory leak에 대해 구체적으로 공부하던 내용을 제 블로그에 정리하고자 합니다.
(출처 : https://stackoverflow.com/questions/6091615/difference-between-on-heap-and-off-heap)
우선 OOME에 대해 알아보기전에 Java의 메모리 관리를 간략히 살펴보겠습니다.
우리가 JVM 내에서 OOME를 정리하기 전에 살펴보아야 할 곳이 바로 Heap 영역과 Metaspace 영역입니다.
heap 영역의 경우 대표적으로 new 키워드로 생성된 인스터스들이 메모리를 할당하여 존재하고 Metaspace의 경우 클래스의 메타데이터가 주로 위치합니다.
추가적으로 Off-heap이라는 부분을 확인해야 합니다.
Off-heap 영역은 Direct ByteBuffer를 이용하여 할당받은 버퍼 공간은 GC 대상이 되지 않습니다. off-heap 공간을 사용하는 대표적인 예로 EHCache와 같은 캐싱 데이터가 존재할 수 있으며 객체 직렬화를 통해 적재시킬 수 있습니다.
실제로 GC 수행횟수를 감소시켜 성능향상을 도모하기 위해 여러 오픈소스가 off-heap 활용을 하고 있습니다.
(그림 1, 정상동작중인 VisualVM 모니터)
(그림 2, OOME일때 VisualVM 모니터, 출처 : https://www.torsten-horn.de/techdocs/jmx.htm)
위 그림의 경우 정상동작 중일 때와 OOME가 발생했을 때 VisualVM에서 모니터링한 화면입니다.
그림을 확인하면 크게 Heap size(주황색), Used heap(파랑색) 그래프로 구성된 것을 볼 수 있습니다.
중요하게 봐야할 그래프는 Used heap(파랑색) 부분입니다.
이 부분이 감소하지 않고 지속적으로 증가하거나 최대 힙 사이즈까지 차게되는 경우가 그림 2 처럼 OOME와 Memory Leak이 발생했다고 예상할 수 있습니다.