관리 메뉴

피터의 개발이야기

[Kotlin] ManagementFactory을 이용한 JVM 모니터링 방법 본문

Programming/Kotlin

[Kotlin] ManagementFactory을 이용한 JVM 모니터링 방법

기록하는 백앤드개발자 2024. 7. 14. 16:09
반응형

ㅁ 들어가며

ㅇ 대량 압축작업 시 OOME(Out Of Memory Exception)의 발생을 방지하기 위한 방법을 찾는 중이다.

ㅇ Kotlin에서 메모리 사용량 모니터링이 가능한 ManagementFactory에 대해서 알게 되어 정리하였다.

 

ㅁ ManagementFactory란?

ㅇ Kotlin에서 ManagementFactory는 Java Management Extensions (JMX) API의 일부로, JVM의 런타임 정보를 모니터링하고 관리하는 데 사용된다.

ㅇ ManagementFactory는 주로 애플리케이션의 성능 모니터링, 디버깅, 그리고 런타임 동작을 제어하는 데 유용하다. 

ㅇ 이 클래스는 java.lang.management 패키지에 속해 있으며, JVM의 다양한 관리 인터페이스에 접근할 수 있는 정적 메서드를 제공하고 있다.

 

ㅇ ManagementFactory의 주요 기능

   - 메모리 사용량 모니터링

   - 스레드 정보 모니터링

   - 가비지 컬렉션 정보 확인

   - 운영체제 정보

   - 클래스 로딩 정보

 

ㅁ 메모리 사용량 모니터링

ManagementFactory의 getMemoryMXBean() 함수를 이용하여 힙 메모리와 비힙 메모리의 사용량을 확인할 수 있다.

 

import java.lang.management.ManagementFactory

fun getMemoryUsage() {
    val runtime = Runtime.getRuntime()
    val memoryMXBean = ManagementFactory.getMemoryMXBean()
    val heapMemoryUsage = memoryMXBean.heapMemoryUsage
    val nonHeapMemoryUsage = memoryMXBean.nonHeapMemoryUsage

    println("== 전체 메모리 사용량 ==")
    println("총 메모리: ${runtime.totalMemory() / 1024 / 1024} MB")
    println("사용 가능한 메모리: ${runtime.freeMemory() / 1024 / 1024} MB")
    println("사죵 중인 메모리: ${(runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024} MB")
    println("최대 메모리: ${runtime.maxMemory() / 1024 / 1024} MB")

    println("\n== 힙 메모리 사용량 ==")
    println("사용 중인 힙 메모리: ${heapMemoryUsage.used / 1024 / 1024} MB")
    println("최대 힙 메모리: ${heapMemoryUsage.max / 1024 / 1024} MB")

    println("\n== 논힙 메모리 사용량 ==")
    println("사용 중인 Non-Heap 메모리: ${nonHeapMemoryUsage.used / 1024 / 1024} MB")
    println("최대 Non-Heap 메모리: ${nonHeapMemoryUsage.max / 1024 / 1024} MB")
}

출력:
######################
# 메모리 사용량 확인

== 전체 메모리 사용량 ==
총 메모리: 258 MB
사용 가능한 메모리: 253 MB
사죵 중인 메모리: 4 MB
최대 메모리: 4096 MB

== 힙 메모리 사용량 ==
사용 중인 힙 메모리: 3 MB
최대 힙 메모리: 4096 MB

== 논힙 메모리 사용량 ==
사용 중인 Non-Heap 메모리: 3 MB
최대 Non-Heap 메모리: 0 MB

ㅇ Runtime 객체를 이용하여 현재 프로세스의 전체 메모리 사용량을 구한다.

ㅇ ManagementFactory.getMemoryMXBean() 함수를 이용하여 힙메모리와 비힙메모리 사용량을 확인할 수 있다.

ㅇ 샘플코드를 실행하면 전체 메모리, 힙메모리, 논힙 메모리 사용량을 확인할 수 있다.

 

ㅁ 스레드 정보 확인

fun getThreadInfo() {
    val threadMXBean = ManagementFactory.getThreadMXBean()
    println("Total thread count: ${threadMXBean.threadCount}")
    println("Peak thread count: ${threadMXBean.peakThreadCount}")
    println("total Started thread count: ${threadMXBean.totalStartedThreadCount}")
    
    val threadIds = threadMXBean.allThreadIds.toList()
    println("all Thread Ids: ${threadIds.toString()}")
    println("get Thread Info: ${threadMXBean.getThreadInfo(threadIds.get(0))}")
}

출력:
######################
# 스레드 정보 확인

Total thread count: 7
Peak thread count: 7
total Started thread count: 7
all Thread Ids: [1, 9, 10, 11, 26, 27, 28]
get Thread Info: "main" prio=5 Id=1 RUNNABLE

ㅇ ManagementFactory.getThreadMXBean() 함수를 이용하여 현재 실행 중인 스레드의 수, CPU 사용량 등을 조회할 수 있다.

 

ㅇ 샘플코드를 실행하면 스레드 갯수 정보와 스래드 목록 및 스래드의 정보를 확인할 수 있다.

 

ㅁ 운영체제 정보

fun getOSInfo() {
    val operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean()
    println("OS Name: ${operatingSystemMXBean.name}")
    println("OS Version: ${operatingSystemMXBean.version}")
    println("Available Processors: ${operatingSystemMXBean.availableProcessors}")
    println("system Load Average: ${operatingSystemMXBean.systemLoadAverage} minutes")
}

출력:
######################
# 운영체제 정보 확인

OS Name: Mac OS X
OS Version: 13.6.1
Available Processors: 16
system Load Average: 1.7490234375 minutes

ㅇ getOperatingSystemMXBean() 함수를 이용하여 시스템 로드, CPU 사용량 등의 OS 관련 정보를 얻을 수 있다.

 

ㅁ 클래스 로딩 정보

fun getClassLoadingInfo() {
    val classLoadingMXBean = ManagementFactory.getClassLoadingMXBean()
    println("Total loaded class count: ${classLoadingMXBean.totalLoadedClassCount}")
    println("Loaded class count: ${classLoadingMXBean.loadedClassCount}")
    println("Unloaded class count: ${classLoadingMXBean.unloadedClassCount}")
}

출력:
######################
# 클래스 로딩 정보

Total loaded class count: 1104
Loaded class count: 1104
Unloaded class count: 0

ㅇ getClassLoadingMXBean() 함수를 이용하여 로드된 클래스의 수, 언로드된 클래스의 수 등을 확인할 수 있다.

 

ㅁ 가비지 컬렉션 정보

fun getGCInfo() {
    val gcMXBeans = ManagementFactory.getGarbageCollectorMXBeans()
    for (gcMXBean in gcMXBeans) {
        println("GC name: ${gcMXBean.name}")
        println("Collection count: ${gcMXBean.collectionCount}")
        println("Collection time: ${gcMXBean.collectionTime} ms")
    }
}

출력:
######################
# 가비지 컬렉션 정보

GC name: G1 Young Generation
Collection count: 0
Collection time: 0 ms
GC name: G1 Concurrent GC
Collection count: 0
Collection time: 0 ms
GC name: G1 Old Generation
Collection count: 0
Collection time: 0 ms

ㅇ getGarbageCollectorMXBeans() 함수를 이용하여 GC 횟수, GC에 소요된 시간 등을 확인할 수 있다.

ㅇ 시스템의 부하가 없으면 GC 지표는 0으로 표시되지만, 부하나 병목이 생기면 GC의 지표를 확인할 필요가 있다.

 

ㅁ 마무리

ManagementFactory를 사용하여 JVM의 다양한 측면을 모니터링하고 관리하는 방법을 정리하였다. 이를 통해 애플리케이션의 성능을 분석하고 문제를 진단할 수 있다. 

 

소소는 여기

ㅁ 함께 보면 좋은 사이트

JMX을 통한 Memory, CPU, GC, Thread 수 구하는 예제

 

반응형
Comments