JVM 성능 모니터링 및 진단 도구 활용

JVM 상태 모니터링의 핵심 요소

Java 애플리케이션의 안정성과 성능을 확보하기 위해 주요 지표를 실시간으로 관찰해야 합니다. 주요 모니터링 항목은 다음과 같습니다:

  • 메모리 사용 현황 (힙 및 비힙 영역)
  • GC(Garbage Collection) 활동 빈도와 지속 시간
  • 메모리 누수 원인 분석

힙 메모리 구성 분석

다음은 주요 메모리 영역의 현재 및 최대 크기를 확인하는 방법입니다.

영역최대 용량 (확인 방법)현재 사용량경고 기준
전체 힙jmap -heap <PID> → MaxHeapSizeeden + survivor + old 영역 합계사용자 설정
비힙 영역perm + native 영역 합계해당 없음
Eden 영역@Eden Space::capacity@Eden Space::used해당 없음
Survivor 0@From Space::capacity@From Space::used해당 없음
Survivor 1@To Space::capacity@To Space::used해당 없음
뉴 세대 (Xmn과 다름)eden + 하나의 survivor 공간해당 영역 사용량해당 없음
오래된 세대 (Old Gen)@concurrent mark-sweep generation::capacity해당 영역 사용량사용자 설정
PermGen (JDK 8 이후는 Metaspace)@Perm Generation::capacity@Perm Generation::used사용자 설정

메모리 설정 파라미터 조회

설정 항목조회 방법
MaxTenuringThresholdjinfo -flag MaxTenuringThreshold <PID>
MinHeapFreeRatiojmap -heap <PID> → MinHeapFreeRatio
MaxHeapFreeRatiojmap -heap <PID> → MaxHeapFreeRatio
뉴 세대 GC 유형jmap -heap <PID> 출력에서 확인
오래된 세대 GC 유형뉴 세대 정보 아래에 포함
클래스 총 수아직 정확한 표준 명령어 없음

C Heap 사용량 확인

시스템 수준에서 메모리 사용량을 확인하려면 다음 명령어 사용:

top
ps aux

메모리 사용자를 식별하기 위한 방법

  • Java 힙: jmap -histo <PID> 또는 jmap -dump:format=b,file=heap.hprof <PID> 후 MAT(Memory Analyzer Tool)로 분석
  • C Heap: Google Perftools (tcmalloc 등) 활용

GC 활동 지표

행동발생 횟수처리 시간 (초)애플리케이션 정지 시간
Full GC#FGC#FGCT-XX:+PrintGCApplicationStoppedTime 옵션 활성화 시 로그에서 확인
Youth GC#YGC#YGCT동일하게 로그에서 확인 가능

추가적인 GC 로깅을 활성화하려면 다음 옵션을 사용합니다:

-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-XX:+PrintGCApplicationStoppedTime
-Xloggc:logs/gc.log

주요 내장 도구 소개

jinfo: 실행 중인 JVM 설정 조회 및 수정

실행 중인 프로세스의 시스템 속성 및 JVM 플래그를 확인하거나 변경할 수 있습니다. 단, 일부 축약된 플래그는 조회되지 않을 수 있으며, 이는 기본값을 확인하는 데 유용합니다.

지원 운영체제: Solaris, Linux

사용 예시:

jinfo -flag MaxTenuringThreshold <PID>

jmap: 힙 메모리 상태 분석

실행 중인 JVM의 물리적 메모리 사용 상황을 조사합니다. 힙 내 객체의 분포를 살펴보고, GC 전후 차이를 비교하기 위해 힙 덤프를 저장하는 것이 좋습니다.

예시 명령어:

jmap -heap <PID>
jmap -dump:format=b,file=heap.hprof <PID>

덤프 파일은 Eclipse Memory Analyzer (MAT)로 분석 가능하며, 객체 수, 메모리 점유율, 스레드 상태 등을 확인할 수 있습니다.

주의: jmap -dump:live 명령은 전체 힙 덤프를 생성하지 않고 살아 있는 객체만 포함하므로, 내부적으로 Full GC를 트리거할 수 있습니다.

jstack: 스레드 상태 확인

실행 중인 애플리케이션의 모든 스레드 상태를 확인하거나, 크래시 발생 시 생성된 core 파일에서 스택 트레이스를 추출할 수 있습니다. 프로그램이 응답하지 않는 경우(허깅 상태)에도 매우 유용합니다.

지원 운영체제: Solaris, Linux

사용 예시:

jstack <PID>

jstat: JVM 실시간 통계 모니터링

JVM 내장 통계 기능을 활용하여 힙/비힙 크기, 클래스 로더, 컴파일러, GC 상태 등을 실시간으로 모니터링합니다.

사용 예시:

jstat -printcompilation -h10 3024 250 600

각 250밀리초마다 출력하고, 600번 반복하며 10줄마다 헤더 재출력.

옵션 설명

  • -h <n>: n줄마다 헤더 표시
  • -t: 시작 시간부터 경과 시간을 첫 번째 컬럼에 표시
  • -J<arg>: JVM 인스턴스 파라미터 수정 (예: -J-Xms48m)
  • <vmid>: 대상 프로세스 ID
  • <interval>: 간격 (밀리초)
  • <count>: 반복 횟수

주요 옵션 및 출력 컬럼 설명

옵션설명
class클래스 로더 동작 통계
compilerJIT 컴파일러 성능
gcGC 관련 힙 상태
gccapacity세대별 힙 용량 정보
gccauseGC 원인 및 최근 발생 사유
gcnew새로운 세대의 자세한 통계
gcnewcapacity새로운 세대의 공간 크기
gcold오래된 세대 통계
gcoldcapacity오래된 세대 용량 정보
gcpermcapacity퍼먼젠 용량 정보
gcutilGC 통계 요약 (백분율 기반)
printcompilation컴파일된 메서드 정보

Java API를 통한 프로그래밍 방식 모니터링

Java 5 이상부터 제공되는 java.lang.management 패키지를 통해 실행 중인 JVM의 다양한 정보를 코드로 접근할 수 있습니다. 이 패키지는 ManagementFactory를 통해 다양한 MBean 인스턴스를 가져올 수 있도록 지원합니다.

예제 1: 현재 로드된 클래스 수 확인

public class ClassLoaderChecker {
    public static void main(String[] args) throws Exception {
        ClassLoadingMXBean bean = ManagementFactory.getClassLoadingMXBean();
        System.out.println("Loaded classes: " + bean.getLoadedClassCount());
    }
}

예제 2: 사용자 정의 MBean 등록 및 모니터링

public interface DemoMBean {
    AtomicLong getInvokeCount();
}

public class DemoImpl implements DemoMBean {
    private final AtomicLong invokeCount = new AtomicLong(0);

    public AtomicLong getInvokeCount() {
        return invokeCount;
    }

    public static final String OBJECT_NAME = "com.redcreen.demo:type=demo";

    public static void register() {
        try {
            ObjectName name = new ObjectName(OBJECT_NAME);
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
            server.registerMBean(new DemoImpl(), name);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

등록 후, jconsole 또는 자체 코드로 해당 데이터를 실시간으로 조회 가능.

태그: JVM monitoring jstack jmap jinfo jstat

6월 7일 21:06에 게시됨