Java 애플리케이션 운영 중 OutOfMemoryError (OOM)와 같은 메모리 관련 이슈는 개발자와 운영자에게 큰 골칫거리입니다. 이런 문제를 진단하는 가장 효과적인 방법 중 하나는 특정 시점의 힙 메모리 상태를 담은 **힙 덤프(Heap Dump)**를 분석하는 것인데요. 수동으로 프로세스 ID(PID)를 찾아서 jcmd 명령어를 실행하는 것은 번거롭고, 특히 긴급한 상황에서는 더욱 그렇습니다.
오늘 이 글에서는 Java 애플리케이션의 힙 덤프 생성을 쉘 스크립트로 자동화하는 방법을 소개합니다. 이를 통해 빠르고 효율적으로 필요한 진단 정보를 확보하고 문제 해결 시간을 단축할 수 있습니다.
왜 힙 덤프 자동화가 필요한가요?
- 신속한 대응: OOM과 같은 문제가 발생했을 때, 수동 개입 없이 즉시 힙 덤프를 생성하여 현상 발생 시점의 메모리 상태를 기록할 수 있습니다.
- 반복적인 작업 제거: 여러 서버에서 동일한 작업을 반복할 필요 없이 스크립트 하나로 일관된 작업을 수행할 수 있습니다.
- 정확성 향상: 수동 작업 시 발생할 수 있는 PID 오입력 등의 실수를 줄여줍니다.
- 스케줄링 가능: 크론(cron) 같은 스케줄러와 연동하여 특정 시간에 주기적으로 힙 덤프를 생성하거나, 모니터링 시스템과 연동하여 특정 조건(예: 메모리 사용량 임계치 초과)에서 자동으로 힙 덤프를 뜨도록 설정할 수 있습니다.
쉘 스크립트로 힙 덤프 생성 자동화하기
아래는 특정 Java 애플리케이션(MYAPP_API.jar)의 PID를 찾아 힙 덤프를 생성하는 쉘 스크립트입니다.
create_heapdump.sh
Bash
#!/bin/bash
# 힙 덤프를 생성할 Java 애플리케이션의 고유한 이름 (명령줄에서 식별 가능한 부분)
APP_NAME="MYAPP_API.jar"
# --- 프로세스 ID (PID) 찾기 ---
# 'pgrep -f'를 사용하여 전체 명령줄에서 APP_NAME에 해당하는 PID를 찾습니다.
PID=$(pgrep -f "${APP_NAME}")
# PID를 찾지 못했다면 오류 메시지를 출력하고 종료합니다.
if [ -z "$PID" ]; then
echo "오류: ${APP_NAME}에 해당하는 프로세스를 찾을 수 없습니다. 종료합니다."
exit 1
fi
echo "${APP_NAME}에 해당하는 PID ${PID}를 찾았습니다."
# --- 힙 덤프 저장 경로 및 파일명 정의 ---
# 힙 덤프 파일을 저장할 디렉토리
HEAP_DUMP_DIR="/home/myapp/api/logs/heapdumps"
# 파일명에 포함될 현재 타임스탬프 (YYYYMMDD_HHMMSS 형식)
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# 최종 힙 덤프 파일 경로 및 이름
HEAP_DUMP_FILE="${HEAP_DUMP_DIR}/heapdump_myapp_api_${TIMESTAMP}.hprof"
# 힙 덤프 디렉토리가 존재하지 않으면 생성합니다.
if [ ! -d "$HEAP_DUMP_DIR" ]; then
echo "힙 덤프 디렉토리를 생성합니다: ${HEAP_DUMP_DIR}"
mkdir -p "$HEAP_DUMP_DIR"
# 디렉토리 생성 실패 시 종료
if [ $? -ne 0 ]; then
echo "오류: 디렉토리 ${HEAP_DUMP_DIR} 생성에 실패했습니다. 종료합니다."
exit 1
fi
fi
# --- jcmd 명령어를 사용하여 힙 덤프 생성 ---
echo "jcmd ${PID}를 사용하여 ${HEAP_DUMP_FILE}에 힙 덤프를 생성합니다..."
jcmd "${PID}" GC.heap_dump "${HEAP_DUMP_FILE}"
# jcmd 명령의 실행 결과 확인
if [ $? -eq 0 ]; then
echo "성공적으로 힙 덤프를 생성했습니다: ${HEAP_DUMP_FILE}"
else
echo "오류: PID ${PID}에 대한 힙 덤프 생성에 실패했습니다."
fi
exit 0
스크립트 사용 방법
- 스크립트 저장: 위의 내용을 create_heapdump.sh와 같은 파일 이름으로 저장합니다.
- 실행 권한 부여: 터미널에서 다음 명령어를 실행하여 스크립트에 실행 권한을 부여합니다.
Bash
chmod +x create_heapdump.sh
- 스크립트 실행: 다음 명령어로 스크립트를 실행합니다.
Bash
./create_heapdump.sh
스크립트 주요 코드 설명
- APP_NAME="MYAPP_API.jar": 힙 덤프를 뜰 Java 애플리케이션의 식별자입니다. ps -ef | grep java 명령 시 출력되는 결과에서 해당 애플리케이션을 유일하게 식별할 수 있는 문자열을 사용하세요. 여기서는 MYAPP_API.jar를 사용했습니다.
- PID=$(pgrep -f "${APP_NAME}"): pgrep 명령어는 프로세스 이름이나 명령줄 패턴을 기반으로 PID를 찾아줍니다. -f 옵션은 전체 명령줄을 대상으로 검색하도록 하여 Java 애플리케이션의 경우 유용합니다.
- HEAP_DUMP_DIR="...", TIMESTAMP=$(date +"%Y%m%d_%H%M%S"), HEAP_DUMP_FILE="...": 힙 덤프 파일이 저장될 경로와 파일명을 정의합니다. 파일명에 타임스탬프를 포함하여 각 덤프가 고유하도록 합니다.
- mkdir -p "$HEAP_DUMP_DIR": 힙 덤프 저장 디렉토리가 없다면 생성합니다. -p 옵션은 상위 디렉토리까지 한 번에 생성해줍니다.
- jcmd "${PID}" GC.heap_dump "${HEAP_DUMP_FILE}": 이 부분이 핵심입니다. jcmd는 JVM(Java Virtual Machine)에 명령을 보내는 도구입니다. 특정 PID에 대해 GC.heap_dump 명령을 실행하여 지정된 경로에 힙 덤프를 생성합니다.
- if [ $? -eq 0 ]; then ... fi: 이전 명령어의 종료 상태를 확인합니다. $? 변수에는 마지막으로 실행된 명령어의 종료 코드가 저장되며, 0은 보통 성공을 의미합니다.
마무리하며
이 쉘 스크립트를 활용하면 Java 애플리케이션의 힙 덤프 생성을 간편하게 자동화할 수 있습니다. 이렇게 생성된 .hprof 파일을 Eclipse Memory Analyzer (MAT)나 VisualVM과 같은 도구로 분석하면 메모리 누수나 비효율적인 객체 사용 등을 효과적으로 진단하고 해결할 수 있을 거예요. 여러분의 Java 애플리케이션이 더욱 안정적으로 운영되기를 바랍니다!
'Dev' 카테고리의 다른 글
푸시한 커밋을 특정시점으로 안전하게 되돌리기 (0) | 2025.07.07 |
---|---|
로컬에서 MSSQL, GitLab, Flyway 환경을 Docker로 구성해서 실습하고 테스트할 수 있는 플래그십 예제 프로젝트 (1) | 2025.06.25 |
윈도우에 Git 설치 - Git 사용(1/5) (0) | 2019.08.26 |