Java Virtual Machine(JVM)은 Java 애플리케이션을 실행하는데 필요한 가상 머신입니다. JVM은 자바 코드(.java 파일)를 바이트코드(.class 파일)로 컴파일한 후 이를 운영체제에 맞게 해석하고 실행합니다.
JVM의 주요 역할 요약
- 바이트코드를 운영체제에 맞는 기계어로 변환하여 실행
- 메모리 관리
- 리소스 관리
JVM의 구성 요소
- ClassLoader:
- 자바 클래스 파일(.class)을 메모리로 로드하는 역할을 합니다. ClassLoader는 프로그램이 실행될 때 필요한 클래스들을 동적으로 로드하며, 이를 통해 자바는 런타임 시에도 새로운 클래스를 로드할 수 있습니다.
- Runtime Data Areas (런타임 데이터 영역):
JVM이 실행될 때 메모리를 여러 영역으로 나누어 관리합니다.- Method Area (메소드 영역):
클래스의 메타데이터, 상수, 정적 변수, 메서드 코드가 저장됩니다. 모든 스레드가 공유하는 영역입니다. - Heap (힙):
객체의 참조값 저장되는 영역입니다. 힙은 모든 스레드에서 공유되며, 가비지 컬렉션이 주로 이 영역에서 발생합니다. - Stack (스택):
각 스레드마다 별도로 할당되는 영역으로, 메소드 호출 시마다 프레임이 생성되며, 지역 변수, 매개변수, 연산 중간 결과가 저장됩니다. - PC Register (프로그램 카운터 레지스터):
각 스레드마다 존재하며, 현재 실행 중인 JVM 명령의 주소를 저장합니다. - Native Method Stack (네이티브 메소드 스택):
자바가 아닌 네이티브 코드(C, C++ 등)로 작성된 메서드를 실행할 때 사용되는 스택입니다.
- Method Area (메소드 영역):
- Execution Engine (실행 엔진):
바이트코드를 실제로 실행하는 부분입니다.- Interpreter (인터프리터):
바이트코드를 한 줄씩 읽고 해석하여 실행합니다. 빠르게 시작할 수 있지만, 반복되는 코드에서는 성능이 떨어질 수 있습니다. - Just-In-Time Compiler (JIT 컴파일러):
성능을 높이기 위해 인터프리터가 반복해서 실행하는 바이트코드를 기계어로 변환하여 캐시하는 역할을 합니다. 이렇게 변환된 기계어는 이후 인터프리터 없이 실행되어 성능을 향상시킵니다. - Garbage Collector (가비지 컬렉터):
힙 영역에서 더 이상 사용되지 않는 객체를 자동으로 정리하여 메모리를 해제하는 역할을 합니다.
- Interpreter (인터프리터):
- Native Method Interface (네이티브 메소드 인터페이스):
Java 애플리케이션이 C/C++로 작성된 네이티브 메소드를 호출할 수 있도록 하는 인터페이스입니다. 이를 통해 Java는 Java 코드 외에도 네이티브 코드를 실행할 수 있습니다. - Native Method Libraries (네이티브 메서드 라이브러리):
JVM이 네이티브 메서드에 접근할 때 필요한 라이브러리들입니다. 이 라이브러리들은 운영체제에 종속적입니다.
JVM의 주요 기능
- 메모리 관리:
JVM은 메모리를 자동으로 관리하는데, 개발자가 직접 메모리를 해제하지 않아도 되는 점이 큰 장점입니다. 이 과정에서 가비지 컬렉터가 중요한 역할을 하며, 사용되지 않는 객체를 자동으로 탐지하여 메모리를 해제합니다. - 플랫폼 독립성:
Java는 "한 번 작성하면 어디서나 실행할 수 있다(Write Once, Run Anywhere)"라는 철학을 가지고 있습니다. 이는 JVM 덕분에 가능하며, Java 바이트코드는 특정 운영체제가 아닌 JVM에서 실행되므로, JVM만 있으면 어떤 운영체제에서도 동일한 바이트코드를 실행할 수 있습니다. - 스레드 관리:
JVM은 여러 스레드를 생성하고 관리하는 기능을 내장하고 있습니다. 자바의 멀티스레딩을 통해 애플리케이션에서 병렬 처리를 쉽게 구현할 수 있습니다. - 가비지 컬렉션:
Java는 메모리 관리를 자동화하는 가비지 컬렉션(Garbage Collection) 기법을 사용합니다. 힙 영역에서 더 이상 참조되지 않는 객체를 자동으로 제거하여 메모리 누수를 방지하고 프로그램 성능을 유지합니다. JVM에는 다양한 가비지 컬렉터가 존재하며, G1 GC, CMS GC, Serial GC, Parallel GC 등이 있습니다.
JVM 튜닝 및 최적화
JVM은 다양한 설정 옵션을 제공하여 성능을 최적화할 수 있습니다. 예를 들어, 힙 크기나 가비지 컬렉터 설정 등을 조정할 수 있습니다.
- 힙 메모리 크기 조정:
- -Xms: 초기 힙 크기를 설정
- -Xmx: 최대 힙 크기를 설정
- 가비지 컬렉터 선택:
- -XX:+UseG1GC: G1 GC를 사용
- -XX:+UseConcMarkSweepGC: CMS GC를 사용.
- -XX:+UseParallelGC: Parallel GC를 사용
- JIT 컴파일러 튜닝:
- -XX:+TieredCompilation: 단계별 컴파일링을 활성화하여 자주 실행되는 코드를 더 빠르게 컴파일합니다.
- -XX:CompileThreshold: 메소드가 JIT 컴파일될 때까지의 호출 횟수를 조정합니다.
- 스레드 풀 크기 조정:
멀티스레드 애플리케이션에서 JVM이 사용하는 스레드 풀의 크기도 조정할 수 있으며, 이는 애플리케이션 성능에 중요한 영향을 미칩니다.
JVM의 실행 과정
- 자바 소스 파일(.java)을 작성하고, 이를 javac 컴파일러로 바이트코드(.class)로 컴파일합니다.
- JVM이 실행되면 ClassLoader가 이 바이트코드를 메모리에 로드합니다.
- Execution Engine은 바이트코드를 해석하거나 JIT 컴파일러로 기계어로 변환하여 실행합니다.
- 실행 중에 JVM은 메모리 영역을 관리하고, 가비지 컬렉터를 통해 필요 없는 메모리를 해제합니다.
'(컴퓨터 언어)Java' 카테고리의 다른 글
데이터 불일치 문제 피하기 : 자바에서 스레드 동기화를 하는 3가지 방법 (0) | 2023.08.14 |
---|---|
java.util.Stack, 실제로는 잘 사용하지 않는 이유는? (0) | 2023.07.31 |
댓글