새발블로그
[JAVA] JVM 본문
자바는 1990년대 초 개발되어, 정말 많은 시스템에서 널리 사용되고 있는 객체 지향 프로그래밍 언어이다.
자바의 강점 중 하나는 플랫폼 독립성이다. 한 번 작성하면 여러 운영체제에서 실행될 수 있기 때문에, "Write Once, Run Anywhere"라는 특성을 갖고 있다.
1. 자바(Java)의 기본 특징
| 플랫폼 독립성 | "Write Once, Run Anywhere" : 한 번 작성하면 어떤 운영체제에서도 실행 가능 |
| 메모리 관리 | 개발자가 직접 관리하지 않고, JVM이 메모리 자동 관리 (GC: Garbage Collection) |
| 바이트 코드 기반 | 자바 코드를 컴파일하면 바이트 코드(.class 파일)로 변환되어 JVM이 실행 |
| JIT 컴파일 | 런타임 시점에 자주 쓰이는 코드를 Native Code(기계어)로 변환해서 성능 최적화 |
| 객체 지향 언어 | 캡슐화, 상속, 다형성, 추상화 같은 OOP 개념에 충실 |
| 느릴 수 있음 | 인터프리트 방식 + VM 계층 추가로 네이티브 앱보다 느릴 수 있음 (하지만 JIT로 많이 개선됨) |
2. JVM (Java Virtual Machine) 이란?
JDK, JRE, JVM 차이 정리
| JVM (Java Virtual Machine) | 실행 엔진 | 바이트 코드를 해석해서 OS에서 실행시킴 |
| JRE (Java Runtime Environment) | JVM + 라이브러리 | 자바 프로그램을 실행할 수 있는 환경 |
| JDK (Java Development Kit) | JRE + 개발 도구 | 자바 프로그램을 개발+실행할 수 있는 환경 (컴파일러, 디버거 포함) |
- JDK = JRE + (컴파일러, 디버거 같은) 개발 툴
- JRE = JVM + 표준 라이브러리
- JVM = 실행기계(가상머신), 바이트코드 실행 담당
→ 개발하려면 JDK 필요,
→ 실행만 하려면 JRE만 있으면 됨
2.1 JVM의 역할
JVM은 자바 프로그램을 실행하는 가상 머신이다. 자바 소스 코드가 컴파일되면 바이트 코드로 변환되는데, 이 바이트 코드를 실제 운영체제에서 실행하는 역할을 맡고 있다.
자바 프로그램을 실행하는 과정은 다음과 같다
- 소스 코드 작성 (.java 파일)
- 컴파일 → .class(바이트 코드) 파일로 변환
- 클래스 로더가 .class 파일을 JVM에 로드
- 바이트 코드 검증기가 보안 검사를 수행
- 실행 엔진이 바이트 코드를 실행
2.2 JVM 메모리 구조
JVM은 여러 개의 메모리 영역으로 구성된다.
- Heap: 자바 객체들이 저장되는 영역. Garbage Collection 대상
- Stack: 각 메소드가 호출될 때 생성되는 지역 변수와 메소드 호출 정보를 저장하는 영역
- Method Area: 클래스 정보, 메서드 정보 등 메타데이터를 저장
- PC Register: 현재 실행 중인 명령어의 주소를 저장
- Native Method Stack: 네이티브 코드(C, OS 메서드 등) 실행에 사용
2.3 JVM의 종류
JVM에는 여러 가지 종류가 존재하며, 주요 JVM으로는 다음과 같다.
- HotSpot JVM: Oracle에서 제공하는 기본 JVM으로, JIT 컴파일 최적화가 강력하여 성능이 뛰어나다
- OpenJ9: IBM에서 개발한 경량화 JVM으로, 메모리 사용이 적고 부팅 속도가 빠르다.
- GraalVM: 여러 언어(Java, Python, JavaScript 등)를 지원하는 최신 JVM으로, Native Image 빌드를 통해 빠른 실행을 제공한다.
3. Garbage Collection (GC)란?
3.1 GC의 역할
Garbage Collection(GC)는 자바에서 메모리 관리를 자동으로 수행하는 시스템이다. GC는 프로그램 실행 중에 더 이상 사용되지 않는 객체들을 찾아서 메모리에서 제거한다. 이를 통해 메모리 누수(Memory Leak)를 방지하고, 개발자가 메모리 해제 작업을 명시적으로 하지 않아도 되게 해준다.
3.2 GC 작동 원리
GC는 자바 힙 영역에 생성된 객체 중 참조되지 않는 객체를 찾아서 자동으로 메모리를 회수한다. 이 과정에서 참조 그래프를 사용하여 루트 객체에서 시작해 연결된 객체들을 추적한다. 참조가 끊어진 객체는 GC에 의해 제거됩니다.
3.3 GC 종류
자바에는 여러 종류의 GC 알고리즘이 있으며, 각 알고리즘은 성능에 따라 다르게 동작한다.
- Serial GC: 단일 스레드로 GC를 수행. 작은 애플리케이션에 적합.
- Parallel GC: 여러 스레드를 사용하여 GC를 병렬로 처리. 큰 시스템에서 유용.
- CMS (Concurrent Mark-Sweep): Old Generation 객체를 비동기적으로 GC하여 중단 시간을 최소화.
- G1 GC: 힙을 여러 영역으로 나누어 필요한 부분만 GC하는 최신 GC 알고리즘으로, 예측 가능한 짧은 중단 시간을 제공합니다.
3.4 GC 최적화
JVM에서는 GC의 성능을 최적화하기 위해 여러 방법을 제공한다. 예를 들어, Young Generation(새로운 객체)을 먼저 GC하고, Old Generation(오래된 객체)은 나중에 GC하는 방식을 사용한다. 이렇게 하면 GC가 자주 발생하는 Young Generation에서 성능 저하를 최소화할 수 있다.
3.4.1 Young Generation에 대한 이해
JVM 힙 영역은 크게 세 가지 주요 구역으로 나뉜다.
- Young Generation: 새로 생성된 객체가 배치되는 영역
- Old Generation: 오래 살아남은 객체들이 이동하는 영역
- Permanent Generation (또는 Metaspace): 클래스 메타데이터와 같은 정보 저장
Young Generation은 자주 생성되고 빠르게 소멸하는 단명 객체들이 주로 존재하는 영역이다. 자바에서 new 키워드를 사용하여 객체를 생성하면, 기본적으로 이 객체는 Young Generation에 할당된다.
3.4.2. Young Generation에서 GC가 자주 발생하는 이유
- GC 대상 객체의 비율이 높음:
Young Generation은 주로 "단명 객체"들로 구성된다. 자주 생성되고 빠르게 소멸하는 객체들이 많기 때문에, 대부분의 객체는 힙에서 "참조되지 않게 되는" 시점이 빠르다. 따라서, 이 영역에 있는 객체들에 대한 Garbage Collection이 자주 발생한다. - Eden 영역과 Survivor 영역:
Young Generation은 주로 3개의 영역으로 나눠진다.- Eden: 새로 생성된 객체들이 배치되는 영역.
- Survivor 1, Survivor 2: Eden에서 살아남은 객체들이 이동하는 영역.
'Language > Java' 카테고리의 다른 글
| [JAVA] SOLID 원칙 (0) | 2025.05.04 |
|---|---|
| [JAVA] 상속 (0) | 2025.05.04 |
| [JAVA] 클래스 (0) | 2025.05.04 |
| [JAVA] 변수 위치 및 메모리 구조 (0) | 2025.05.04 |
| 점프 투 자바 메모 (0) | 2023.08.09 |