TL;DR

  • Midden은 JDK 설치 없이 단일 정적 바이너리로 JVM 힙 덤프를 분석하고, 전체 객체 그래프와 도미네이터 트리를 구성해 객체별 유지 크기(retained size)를 산출함.
  • jcmd, jmap, -XX:+HeapDumpOnOutOfMemoryError로 생성한 .hprof 덤프와 압축 파일을 읽고, 보유 객체·누수 의심 항목·객체 참조 경로를 확인함.
  • 클래스·객체·문자열 검색, 두 덤프 간 증가량 비교, JSON 출력, 대화형 셸을 제공함.
  • 기본적으로 라이브 힙의 10% 이상을 유지하는 객체나 클래스를 누수 의심 항목으로 분류하며, 참조 유형과 크기 계산 방식을 옵션으로 조정함.
  • 덤프 인덱스를 캐시해 후속 실행을 빠르게 시작하며, 객체당 약 90바이트의 메모리를 사용하고 덤프 자체는 스트리밍 방식으로 처리함.

설치

사용법

  • .hprof 덤프는 압축되지 않은 파일뿐 아니라 gzip 압축 파일, tar 파일, zip 파일 안에 들어 있는 형태도 읽음.
  • 기본 실행은 전체 보고서를 출력하며, --class ObjectMapper는 해당 클래스의 참조자·소유자·루트 경로를, --object 0x7f3a1234는 단일 객체의 필드·소유자·유지 대상 정보를 출력함.
  • --find jdbc:postgresql은 해당 문자열이 포함된 문자열 객체와 이를 보유하는 대상을 찾고, --where 'StandardSession.isValid=false'는 조건에 맞는 대상을 찾음.
  • --baseline before.hprof는 두 덤프 사이에서 증가한 항목을 비교하고, --only suspects --json은 스크립트용 JSON 결과를 출력함.
  • --shell은 파일을 다시 읽지 않고 결과를 탐색하는 대화형 셸을 실행함.
  • 기본 보고서 섹션은 heap, suspects, biggest, classes, collections, threads, locals, loaders, strings, arrays, boxed, references, garbage, system, direct, baseline임. --only와 --skip으로 섹션을 선택하거나 제외할 수 있으며, 모든 플래그는 midden --help에서 확인 가능함.

누수 의심 항목과 계산 옵션

  • 누수 의심 항목은 라이브 힙의 10% 이상을 유지하는 객체 또는 클래스임.
  • 예시 보고서에서는 Big 클래스가 983.7MB(64.1%)를 유지하며, 정적 필드 Big.MAP의 java.util.HashMap과 그 테이블이 979.5MB(63.8%)를 차지하는 누적 지점으로 표시됨.
  • 해당 예시에서는 27,999,745개 객체가 유지되며, 그중 int[] 4,000,000개가 183.1MB, HashMap$Node 4,000,000개가 183.1MB를 차지함.
  • 기본 설정에서는 소프트·약한·팬텀 참조의 대상(referent)을 보유 메모리로 계산하지 않으며, --include-soft 또는 --include-weak로 포함할 수 있음.
  • 기본 크기 계산은 MAT 방식을 따르며, --sizes compressed를 사용하면 HotSpot의 압축 객체 포인터(compressed-oops) 기준 메모리 크기를 계산함.
  • 첫 실행은 인덱스를 <dump>.midden/에 캐시해 이후 실행에서 보고서부터 시작하며, --no-cache로 캐시를 끌 수 있음.
  • 예상 메모리 사용량은 객체당 약 90바이트이며, 힙 덤프 파일 자체는 스트리밍 처리됨.

개발

  • 연속 통합(CI)에서 cargo fmt --check와 cargo clippy --all-targets -- -D warnings를 실행함.

라이선스

  • 라이선스는 MIT이며, 세부 내용은 LICENSE에서 확인 가능함.