Java 프로그램의 메모리 사용량 확인이 필요한 이유
동적 메모리를 많이 사용하는 장기 실행(long-running) Java 프로그램의 경우, 힙(heap) 공간이 부족해지면 OutOfMemoryError가 발생할 수 있습니다. 이러한 오류를 사전에 예방하려면 프로그램이 현재 얼마나 많은 메모리를 사용하고 있는지 주기적으로 모니터링하는 것이 중요합니다.
Java에서는 Runtime 클래스를 통해 JVM의 메모리 상태를 손쉽게 확인할 수 있습니다. 아래 예제는 프로그램에서 사용 중인 여유 힙 공간을 검사하고, 힙 사용률이 90%를 초과하면 가비지 컬렉터(Garbage Collector)를 명시적으로 호출하는 방법을 보여줍니다.
주요 Runtime API 정리
- maxMemory(): JVM이 사용할 수 있는 최대 힙 크기(바이트 단위)
- totalMemory(): 현재 JVM에 할당된 전체 힙 크기
- freeMemory(): 할당된 힙 중 아직 사용되지 않는 여유 공간
현재 사용 중인 메모리는 totalMemory() - freeMemory()로 계산할 수 있으며, 이 값을 최대 힙 크기로 나누어 백분율로 표현하면 실제 힙 사용률을 파악할 수 있습니다.
예제 코드
public class GCTest {
public void runGC() {
Runtime runtime = Runtime.getRuntime();
long memoryMax = runtime.maxMemory();
long memoryUsed = runtime.totalMemory() - runtime.freeMemory();
double memoryUsedPercent = (memoryUsed * 100.0) / memoryMax;
System.out.println("memoryUsedPercent: " + memoryUsedPercent);
if (memoryUsedPercent > 90.0)
System.gc();
}
public static void main(String args[]) {
GCTest test = new GCTest();
test.runGC();
}
}실행 결과
memoryUsedPercent: 0.07187129404943532
위 출력 결과를 보면 현재 힙 사용률이 약 0.07%로 매우 낮으므로 가비지 컬렉션이 호출되지 않습니다.
주의 사항: System.gc()의 블로킹 동작
System.gc()를 호출하면 해당 스레드는 가비지 컬렉션이 완료될 때까지 블로킹(blocking)됩니다. 즉, GC 작업이 끝나기 전까지 다음 코드가 실행되지 않습니다.
따라서 실시간 성능이 중요한 애플리케이션에서는 이 코드를 별도의 백그라운드 스레드에서 실행하여, 메인 스레드의 작업 흐름이 멈추지 않도록 구성하는 것이 좋습니다. 또한 주기적인 메모리 점검이 필요하다면 스케줄러(예: ScheduledExecutorService)와 함께 활용하면 더욱 효과적입니다.