JVM은 무엇을 하는가
Java를 공부하다 보면 JDK, JRE, JVM이라는 용어를 자주 보게 된다. 이 중 JVM은 가장 많이 언급되지만, 정작 역할을 한 문장으로 설명하려 하면 막막해지기 쉽다.
JVM은 단순히 “Java 프로그램을 실행하는 가상 머신”이 아니다. 더 정확히 말하면, 바이트코드를 실행하고 메모리 관리, 클래스 로딩, 가비지 컬렉션, JIT 컴파일 같은 런타임 기능을 제공하는 실행 환경이다.
왜 JVM이 필요한가
Java는 소스 코드를 바로 CPU가 이해하는 기계어로 배포하지 않는다. 대신 .java 파일을 컴파일해서 .class 바이트코드로 만든다.
이 바이트코드는 특정 OS나 CPU에 종속되지 않는다. 그리고 그 바이트코드를 실제 머신에서 실행 가능하게 해주는 계층이 JVM이다.
이 구조 덕분에 Java는 흔히 다음 특징으로 설명된다.
Write Once, Run Anywhere
즉, 같은 바이트코드를 여러 환경에서 실행할 수 있는 이유는 JVM이 플랫폼 차이를 흡수해주기 때문이다.
실행 흐름을 단순하게 보면
Java 프로그램 실행 흐름은 대략 다음과 같다.
- 소스 코드 작성
javac로 바이트코드 컴파일- JVM이 바이트코드를 로드
- 인터프리팅 또는 JIT 컴파일로 실행
여기서 중요한 점은 JVM이 단순 실행기만이 아니라는 것이다. 실행 과정에서 필요한 여러 런타임 서비스를 함께 제공한다.
JVM이 하는 핵심 역할
1. 클래스 로딩
JVM은 프로그램 시작 시 모든 클래스를 한 번에 올리지 않는다. 필요한 시점에 클래스를 읽어 들이고, 링크하고, 초기화한다.
이 과정에는 보통 다음이 포함된다.
- 로딩
- 링크
- 초기화
클래스 로더 구조 덕분에 표준 라이브러리와 사용자 코드, 외부 라이브러리를 구분해 다룰 수 있다.
2. 메모리 관리
JVM은 런타임 메모리 영역을 관리한다. 대표적으로 자주 언급되는 영역은 다음과 같다.
- Heap
- Stack
- Metaspace
- PC Register
- Native Method Stack
실무에서는 특히 Heap과 Stack 구분을 먼저 이해하는 것이 중요하다.
- Heap: 객체가 생성되는 영역
- Stack: 메서드 호출 정보와 지역 변수가 쌓이는 영역
3. Garbage Collection
JVM은 더 이상 참조되지 않는 객체를 자동으로 회수한다. 이 기능이 있어 개발자가 직접 메모리를 해제하지 않아도 된다.
대신 GC가 언제, 얼마나 오래 동작하는지는 성능에 큰 영향을 준다. 그래서 JVM을 이해한다는 것은 GC를 포함한 메모리 동작을 이해하는 것과 거의 같다.
4. 실행 엔진
JVM은 바이트코드를 실제로 실행해야 한다. 여기에는 크게 두 방식이 있다.
- 인터프리터
- JIT 컴파일러
인터프리터는 바이트코드를 한 줄씩 해석하며 실행한다. 시작은 빠르지만 반복 실행 구간에서 비효율적일 수 있다.
JIT 컴파일러는 자주 실행되는 코드를 네이티브 코드로 변환해 성능을 끌어올린다. 그래서 Java는 초기 구동 이후 성능이 점점 안정되는 특성을 보이기도 한다.
JDK, JRE, JVM의 차이
이 세 용어는 자주 같이 나오므로 같이 구분해두는 편이 좋다.
- JVM: 바이트코드를 실행하는 가상 머신
- JRE: JVM + 실행에 필요한 라이브러리
- JDK: JRE + 개발 도구(
javac,javadoc등)
즉, 개발자는 JDK를 사용하고, 실행 관점에서는 JVM이 핵심이다.
왜 실무에서 JVM 이해가 중요한가
JVM을 깊게 보지 않아도 Spring 애플리케이션은 돌아간다. 하지만 문제를 분석하려면 JVM을 모르면 막히는 경우가 많다.
예를 들면:
- 메모리 사용량이 왜 급증하는지
- GC pause가 왜 길어지는지
- 스레드 덤프에서 어디가 막히는지
- CPU 사용량이 높은데 왜 코드상으로는 단순해 보이는지
이런 문제는 결국 JVM이 런타임에서 무엇을 하고 있는지를 알아야 해석할 수 있다.
JVM을 공부할 때 먼저 잡아야 할 축
처음부터 구현 세부사항을 다 보려 하면 오히려 흐름을 놓치기 쉽다. 우선은 다음 축으로 이해하는 편이 좋다.
- 클래스가 어떻게 로드되는가
- 객체가 어디에 저장되는가
- GC가 어떻게 메모리를 회수하는가
- 인터프리터와 JIT가 어떻게 협력하는가
이 네 가지를 이해하면 대부분의 JVM 관련 개념이 어디에 속하는지 감이 생긴다.
정리
JVM은 단순히 Java 코드를 실행해주는 도구가 아니라, Java 애플리케이션이 동작하는 런타임 그 자체에 가깝다.
- 바이트코드를 실행하고
- 클래스를 로드하고
- 메모리를 관리하며
- GC와 JIT를 통해 성능과 안정성을 조율한다
그래서 Java를 오래 다룰수록 JVM은 선택 과목이 아니라 필수 기반이 된다. 프레임워크 위에서 개발하더라도, 실제 장애와 성능 문제는 결국 JVM 레이어에서 드러나는 경우가 많기 때문이다.
댓글
아직 댓글이 없습니다