기초 지식/Java
JVM에 관하여
MarrRang
2021. 7. 24. 23:36
Java는 쓰는데 JVM이 뭐지?
Java를 사용하는 데에는 아주 간단한 과정이 있습니다. 자신의 OS에 맞는 JDK를 설치하고 내가 짠 Java 코드를 javac 명령어로 실행시키면 프로그램이 구동됩니다.
근데 이러한 과정은 맥, 윈도우, 리눅스 모두 같은 과정을 거쳐서 사용할 수 있습니다. 이것은 Java 언어의 특성이자 JVM을 이용해서 가능한 일입니다.
JVM이란?
- Java Virtual Machine
- 자바 바이트 코드를 해석하고 실행
- 자바 애플리케이션을 클래스 로더(Class Loader)를 통해 읽어서 자바 API와 함께 실행
- 자바의 WORA(Write Once Run Anywhere) 컨셉을 위해 사용되는 소프트웨어
JVM은 우리가 흔히 사용하는 프로그램들과 똑같은 소프트웨어입니다. 단지 자바 소스파일을 해석하고 실행하기 위한 소프트웨어일 뿐이죠.
JVM 구조
JVM에 Java Source File을 실행하도록 하고 싶어!!
JVM에 Java Source File을 실행하도록 명령한다면 위와 같은 구조의 JVM을 통해서 실행되게 됩니다. 각 구성 파트를 하나씩 살펴보도록 하겠습니다.
1. 클래스 로더(Class Loader)
클래스 로더는 Java Byte를 검증하고 해석해서 실제 물리적 메모리에 로드해주는 역할을 합니다.
그리고 내부에는 3가지 서브시스템 Loading, Linking, Initialiation으로 구성되어 있습니다.
- Loading
Loading 서브시스템은 내부에서 각 Loader들을 순서대로 호출합니다.
- Bootstrap Class Loader
기본 자바 API 라이브러리 로드 - Extension Class Loader
자바 확장 코어 클래스 파일 로드, Platform Class Loader라고도 불린다. 클래스 파일은 JDK 확장 디렉터리에 로드된다. - Application Class Loader
System Class Loader라고도 불리며 애플리케이션 레벨의 클래스들을 로드한다. Classpath 내 클래스 파일 혹은 "-classpath, -cp" 명령어 옵션이 있는 파일을 로드한다.
- Bootstrap Class Loader
- Linking
Linking은 로드한 클래스 파일들을 검증하고 메모리에 할당하는 역할을 합니다.
- Verify
자바 바이트 코드 검증, JVM에서 사용가능한 형태인지 확인합니다. 비용이 매우 커서 -Xverify:none 옵션을 통해 끌 수 있습니다. - Prepare
정적변수를 메모리에 할당합니다. 초기화가 아닌 Default 값(ex. int -> 0)도 할당합니다. - Resolve
Symbolic Reference를 Direct Reference로 할당합니다. Java Class 파일은 Runtime 시 메모리 할당을 할 수 있도록 Symbolic Reference만 가지고 있습니다. 이를 실제 메모리의 물리적 주소로 할당하는 것이 Direct Reference로 할당하는 작업입니다.
- Verify
- Initialization
모든 정적 변수가 자바 코드에 명시된 값으로 초기화 되며 정적블록(Static Block)이 실행됩니다.
2. Execution Engine
- Load 된 바이트 코드를 실행하는 Runtime Module이다.
- ClassLoader에 의해 JVM으로 Load된 Class 파일들은 RDA에 Method Area에 배치된다.
- JVM이 Method Area의 바이트 코드를 Execution Engine에 제공한다.
- 바이트 코드를 읽을 때 Interpreter 방식, JIT compiler 방식을 섞어서 사용한다.
- Interpreter
바이트 코드를 한 줄씩 해석하고 실행합니다. 속도가 느립니다. - JIT (Just In Time) / Dynamic Translation
프로그램 실행 시점에 각 OS에 맞는 Native Code로 변환하여 실행합니다. 이를 통해서 실행 속도가 개선되었지만 Native Code로 변환하는 비용이 발생합니다. 따라서 이 비용 때문에 Interpreter와 섞어서 사용합니다.
- Interpreter
3. Runtime Data Area
Rutime Data Area 내부에는 5가지 영역으로 이루어져 있습니다.
- Method Area
- 클래스, 변수, Method, Static 변수, 상수 등의 주소 값이 저장되는 영역
- 모든 Thread가 공유
- Heap Area
- new 명령어로 생성된 인스턴스와 객체가 저장되는 영역
- Garbage Collection이 일어나는 영역
- 모든 Thread가 공유
- https://marrrang.tistory.com/52?category=937995 참조
- Stack Area
- Method 내에서 사용되는 값들 (매개변수, 지역변수, 리턴 값 등)이 저장되는 구역
- 메서드가 호출/완료될 때 LIFO(Last In First Out)으로 하나씩 생성/제거
- 각 Thread별로 하나씩 생성
- PC Register
- 현재 수행 중인 JVM 명령의 주소 값을 저장
- CPU의 Register와 역할이 유사
- 각 Thread별로 하나씩 생성
- Native Method Stack
- 다른 언어의 메서드 호출을 위해 할당되는 구역으로 언어에 맞게 Stack이 형성되는 구역
4. JNI (Java Native Interface)
- JDK의 일부로 Java Code와 Native Application, Library들을 연결시켜주는 Interface
- Native Application : C, C++, Assembly와 같은 언어로 작성된 애플리케이션
- 예시 : Java Code로 만들어진 앱과 안드로이드 라이브러리(C/C++)를 연결
3. 정리
- 자바의 WORA(Write Once Run Anywhere) 컨셉을 위해 사용되는 소프트웨어
- 자바 바이트 코드를 해석하고 실행한다.
- 클래스 로더, Execution Engine, Runtime Data Area로 이루어져 있다
- 다른 언어와의 연동을 위해 JNI (Java Native Interface)가 있다.
반응형