DevLog

엔지니어링 블로그를 한 곳에서 탐색하고, 최근 발행 흐름을 빠르게 파악할 수 있는 서비스 입니다.

Quick Links

  • Latest Feed
  • Engineering Directory

Support

  • 소개
  • 개인정보처리방침

Contribute

  • 원하는 블로그 추가 (준비 중)
  • Feedback

© 2026 DevLog Inc. All rights reserved.

본 사이트는 공개 RSS 피드를 통해 콘텐츠를 수집하며, 모든 콘텐츠의 저작권은 원저작자에게 있습니다.

Back to Feed
Read Original

Contents

Continue Reading

  • More from 여기어때
  • Related reads#JVM
#Backend

JVM heap은 멀쩡한데 왜 메모리가 터질까? — Docker 환경 네이티브 메모리 삽질기 (Part 2)

JVM heap은 멀쩡한데 왜 메모리가 터질까? — Docker 환경 네이티브 메모리 삽질기 (Part 2)
01

Summary

JVM 힙은 멀쩡한데 컨테이너가 죽는다면? 범인은 '보이지 않는' 네이티브 메모리!

Docker 환경에서 자바 개발자를 괴롭히는 네이티브 메모리 누수를 추적하고 해결하는 실전 워크플로우

본 아티클은 JVM 힙 모니터링의 한계를 넘어, Docker 컨테이너 환경에서 발생하는 네이티브 메모리 누수 문제를 해결하는 과정을 다룹니다. jemalloc과 async-profiler를 조합해 힙 외부의 메모리 할당 원인을 규명하고, 실무에서 놓치기 쉬운 자원 해제 패턴과 메모리 할당기 튜닝법을 상세히 가이드합니다.

  • 01힙 덤프나 GC 로그로는 절대 잡히지 않는 네이티브 malloc 영역의 메모리 누수 원인 분석
  • 02getResourceAsStream 사용 시 내부적으로 생성되는 Inflater 객체가 유발하는 암묵적인 누수 메커니즘 규명
  • 03jemalloc + jeprof 조합으로 네이티브 C 심볼 단위까지 파고드는 정밀 프로파일링 기법
  • 04async-profiler를 활용해 네이티브 할당을 유발한 실제 자바 비즈니스 로직 역추적
  • 05glibc arena 설정 및 jemalloc 튜닝이 실제 RSS에 미치는 영향력을 수치로 비교 검증

+RECOMMENDATION

Docker 기반의 Java 서비스를 운영하며 원인 모를 OOM 현상을 겪고 있다면, 반드시 NMT와 jemalloc 프로파일링을 병행해보길 권장합니다. 특히 리소스 스트림이나 압축 관련 클래스 사용 시 명시적인 자원 해제 처리를 최우선으로 검토하십시오.

The Problem

JVM 힙 메모리는 정상적으로 관리되고 있음에도 불구하고 Docker 컨테이너의 RSS가 지속적으로 상승하여 리눅스 OOM Killer에 의해 프로세스가 종료되는 현상이 발생했습니다. 이는 NMT(Native Memory Tracking)로도 추적되지 않는 영역에서 발생하는 메모리 할당으로 인해 자바 개발자가 인지하기 어려운 사각지대였습니다.

The Solution

네이티브 메모리 할당 추적을 위해 jemalloc과 jeprof를 사용하여 네이티브 콜그래프를 분석하였고, async-profiler의 '-e alloc' 옵션을 통해 해당 할당을 유발한 자바 코드 경로를 매핑했습니다. 이를 통해 JAR 리소스를 읽을 때 명시적으로 닫지 않은 Inflater 객체가 네이티브 zlib 버퍼를 해제하지 못하고 누적됨을 확인했습니다.

The Result

리소스 스트림을 명시적으로 닫는 코드 수정만으로 RSS가 기준치(1328MB) 대비 절반 이하인 516MB로 감소하는 근본적인 해결 결과를 얻었습니다. 또한 glibc의 arena 튜닝이나 jemalloc 교체 등 인프라 레벨의 완화책들을 수치 기반으로 검증하여 상황별 최적의 메모리 관리 방안을 도출했습니다.

Trade-off

jemalloc 교체는 메모리 파편화 완화에 효과적이지만, Docker 컨테이너 환경에서는 기본 설정 시 오히려 dirty page를 점유하여 RSS가 증가할 수 있으므로 'dirty_decay_ms'와 같은 추가 튜닝이 필수적입니다.

03

Key Concepts

Concept · 01

RSS (Resident Set Size)

프로세스가 실제 물리 메모리(RAM)에 점유하고 있는 용량을 의미하며, JVM 힙 외에도 스택, 코드, 네이티브 라이브러리 할당 영역을 포함합니다.

  • Docker 컨테이너의 OOM Killer가 프로세스 종료 여부를 결정할 때 참조하는 핵심 지표입니다.
  • JVM 힙이 정상임에도 RSS가 한도를 초과하면 컨테이너가 강제 종료될 수 있음을 본문에서 강조합니다.
Concept · 02

jemalloc

멀티스레드 환경에서 메모리 파편화를 줄이고 할당 속도를 높이기 위해 설계된 범용 메모리 할당기입니다.

  • 네이티브 메모리 누수를 추적하기 위해 jeprof와 함께 사용되어 메모리 할당 경로를 시각화하는 도구로 활용됩니다.
  • LD_PRELOAD를 통해 런타임에 기본 glibc 할당기 대신 적용하여 성능과 메모리 효율을 개선할 수 있습니다.
Concept · 03

Inflater / zlib

자바에서 ZIP 파일이나 압축된 데이터를 풀 때 사용하는 클래스로, 내부적으로 네이티브 라이브러리인 zlib를 호출합니다.

  • 사용자가 직접 new Inflater()를 호출하지 않아도 getResourceAsStream 등 내부 로직에 의해 암묵적으로 생성될 수 있습니다.
  • 수행이 끝난 후 명시적으로 close() 또는 end()를 호출하지 않으면 네이티브 메모리 버퍼가 즉시 해제되지 않아 누수의 원인이 됩니다.
Continue reading · same source

여기어때More from 여기어때

View all posts from 여기어때
  • EKS 컨테이너 메모리 스파이크 추적기

    EKSPage CacheLogback
    2일 전
  • SRE 업무에 AI 녹여내기 — 2편: Alert Adviser로 장애 원인 분석 자동화

    GrafanaMCPSlack Bot
    6일 전
  • SRE 업무에 AI 녹여내기 — 1편: Smart RI Calc로 인프라 비용 산정 자동화

    SREAWS KarpenterCost Estimation
    6일 전
  • WebFlux 전환 부하 테스트를 다시 쓴 이야기

    WebFluxSpring BootLoad Testing
    1주 전
  • 데드락을 해결하려다, 락을 줄이게 된 이야기

    MySQL InnoDBDeadlockPessimistic Lock
    1주 전

Related reads#JVM

Explore #JVM
여기어때·EKS

EKS 컨테이너 메모리 스파이크 추적기

#JVM2일 전
SSG

돌아오지 않는 메모리를 찾아서

#JVM1개월 전
여기어때

JVM heap은 멀쩡한데 왜 메모리가 터질까? — Docker 환경 네이티브 메모리 삽질기 (Part 1)

#JVM2개월 전
라포랩스·Spring Boot

Spring Boot Startup Time 최적화 : 90초에서 30초까지의 여정(feat. 오픈소스 기여)

#JVM4개월 전
카카오페이

배포 직후 발생하는 응답 지연을 해결하기 위한 여정 (feat. JVM 웜업)

#JVM6개월 전

Source

여기어때
여기어때
Engineering Blog

Published · July 1, 2026

Topics

JVMDockerMemory Leakjemallocasync-profiler