JDK vs JRE
JDK (Java Development Kit)
- 자바를 개발 시 필요한 라이브러리와 javac, javadoc 등의 개발 도구 포함
- 자바 프로그램을 실행시키기 위한 JRE(Java Runtime Environment) 포함
- Java SE (Java Standard Edition)
- 가장 기본이 되는 표준 에디션의 자바 플랫폼으로 자바 언어의 핵심 기능 제공
- Java EE (Java Enterprise Edition)
- 대규모 기업용 에디션, SE 확장판
JRE (Java Runtime Environment)
- JVM과 자바 프로그램을 실행시킬 때 필요한 라이브러리 API를 함께 묶어서 배포되는 패키지
- JRE은 기본적으로 JDK에 포함되어 있어 JDK를 설치하면 함께 설치된다.
JVM (Java Virtual Machine)
- 자바 가상 머신의 약자로, 자바를 실행하는 프로그램
- 자바 언어뿐만 아니라 코틀린, 스칼라 언어에서도 JVM 동작 방식을 따른다.
- JVM을 사용하면 자바 프로그램을 모든 플랫폼에서 제약 없이 동작할 수 있다.
- OS에 종속적이지 않아, 운영체제로부터 독립적으로 프로그램을 제약 없이 실행할 수 있다. ⇒ 이식성이 좋다.
- Java 언어로 작성한 소스파일은 운영체제가 직접 실행하는 것이 아닌, JVM을 거쳐서 운영체제와 상호작용을 하게 된다.
- 컴파일된 코드와 하드웨어/OS 사이에서, 하드웨어/OS 환경에 알맞게 JVM이 바이트 코드로 변환해 주기 때문이다.
- 자바 프로그램과는 달리 자바 가상 머신(JVM)은 운영체제에 종속적이므로, 각 운영체제에 맞는 자바 가상 머신을 설치해야 한다.
- Java는 C언어와 달리 두 번의 컴파일 과정으로 인해 속도의 문제가 발생한다.
- 이를 보완하기 위해 JIT 컴파일러 등장
- 필요한 부분만을 기계어로 바꾸어 줌으로써 성능 향상을 가져오도록 했지만, C언어의 실행 속도는 따라잡지 못한다.
- 게임이나 임베디드에서 C계열 언어를 사용하는 이유가 바로 이 때문이다.
JVM 실행 과정
- JVM은 OS로부터 메모리(Runtime Data Area)를 할당받는다.
- 컴파일러(javac)는 자바 소스코드(.java)를 읽어, JVM가 이해할 수 있는 바이트 코드 (.class)로 변환한다.
- Class Loader는 동적 로딩을 통해 필요한 클래스들을 로딩 및 링크하여, Runtime Data Area로 로딩한다.
- 로딩된 클래스는 Execution Engine을 통해 해석 및 실행되며, Garbage Collector의 작동과 Thread 동기화가 이루어진다.
JVM의 구조
- 클래스 로더 (Class Loader)
- 실행 엔진 (Execution Engine)
- 인터프리터 (Interpreter)
- JIT 컴파일러 (Just-in-Time)
- 가비지 콜렉터 (Garbage Colletor)
- 런타임 데이터 영역 (Runtime Data Area)
- 메서드 영역
- 힙 영역
- PC Register
- 스택 영역
- 네이티브 메서드
- 네이티브 메서드 인터페이스 (Native Method Interface)
- 네이티브 메서드 라이브러리 (Native Method Library)
1. 클래스 로더 (Class Loader)
- JVM 내로 클래스 파일 (*.class)을 동적으로 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈
- 동적 로딩 : 클래스를 메모리에 한 번에 로딩하지 않고, 애플리케이션에서 필요한 경우 동적으로 메모리에 적재한다.
- 로드된 바이트 코드를 엮어서 JVM의 메모리 영역인 Runtime Data Area에 배치한다.
2. 실행 엔진 (Execution Engine)
- 클래스 로더를 통해 Runtime Data Area에 배치된 바이트 코드를 명령어 단위로 읽어서 실행한다.
- 바이트 코드를 실제로 JVM 내부에서 컴퓨터가 실행할 수 있는 형태로 변경한다.
- 실행 엔진은 인터프리터와 JIT 컴파일러 두 가지 방식을 혼합하여 바이트 코드를 실행
- 인터프리터
- 바이트 코드 명령어를 하나씩 읽어서 해석하고 바로 실행
- 같은 메서드라도 여러 번 호출이 된다면 매번 해석하고 수행해야 하므로 전체적인 속도가 느리다.
- JIT 컴파일러
- 인터프리터의 단점을 보완하기 위해 도입
- 반복되는 코드를 발견하여 바이트 코드 전체를 컴파일하여 Native Code로 변경하고 이후에는 해당 메서드를 인터프리팅 하지 않고 캐싱해 두었다가 네이티브 코드로 직접 실행하는 방식
- 하나씩 인터프리팅하여 실행하는 것이 아니라, 컴파일된 네이티브 코드를 실행하는 것이기 때문에 전체적인 실행 속도는 개선할 수 있다.
- 바이트 코드를 Native Code로 변환하는 데에도 비용이 소모되므로, 모든 코드에 대해서 JIT 컴파일러 방식을 사용하지 않고 인터프리터 방식을 사용하다 일정 기준이 넘어가면 JIT 컴파일 방식으로 명령어를 실행하는 식으로 진행
- 인터프리터
- 가비지 컬렉션
- Heap 메모리 영역에서 사용하지 않는 메모리를 자동으로 회수한다.
3. 런타임 데이터 영역 (Runtime Data Area)
JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터를 적재하는 영역
- Method Area
- JVM이 시작될 때 생성되는 영역이며, 프로그램이 종료될 때 해제된다.
- 자바 프로그램 시작 시 초기화되는 static 변수, static 메서드, 클래스 정보만 저장된다.
- 모든 스레드에서 공유하는 영역
- Runtime Constant Pool
- 클래스/인터페이스가 로딩될 때 Method Aread에 할당되는 자료구조
- 각 클래스/인터페이스마다 별도의 constant pool 테이블이 존재, 클래스 생성할 때 참조해야 할 정보들을 상수로 가지고 있는 영역
- Constant Pool을 통해 메서드나 필드의 실제 메모리 상 주소를 찾아 참조
- Heap Area
- 런타임 시 동적으로 할당된 데이터를 저장하는 영역
- new 연산자로 생성되는 클래스와 인스턴스 변수, 배열 타입 등 Reference Type이 저장되는 영역
- 모든 스레드에서 공유하는 영역
- GC(Garbage Collector)의 대상이 되어, 참조되지 않는 객체는 자동으로 제거된다.
- Young(Eden, survivor 0, survivor 1), Old, Permanent 영역으로 구분된다.
- 런타임 시 동적으로 할당된 데이터를 저장하는 영역
- Stack Area
- 메서드 호출 시 메서드의 지역변수, 매개변수, 리턴 값 및 연산 중 발생하는 임시 데이터를 저장하는 영역
- 메서드 호출 시마다 각각의 스택 프레임이 생성되고, 메서드가 종료되면 프레임별로 삭제된다.
- 각 스레드마다 하나씩 존재하며, 스레드가 초기화될 때 할당된다.
- 스레드가 종료되면 해당 스레드의 Stack도 소멸된다.
- PC Register
- 스레드가 시작될 때 생성되며, 현재 수행 중인 JVM 명령어 주소를 저장하는 공간
- 스레드마다 하나씩 존재하며, 현재 수행 중인 명령어의 주소를 가리킨다.
- Native Method Stack
- 자바 코드가 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역
- 자바 외의 JIT 컴파일러에 의해 변환된 C/C++로 작성된 Native Code를 실행하기 위한 영역
- JNI(Java Native Interface)를 통해 호출되는 C/C++ 함수의 매개변수, 지역변수 등을 저장하는 영역
4. 네이티브 메서드 인터페이스 (Native Method Interface)
- 자바가 다른 언어로 만들어진 애플리케이션과 상호 작용할 수 있는 인터페이스를 제공하는 프로그램
- JVM이 Native Method를 적재하고 수행할 수 있도록 한다.
- 하지만 실질적으로 제대로 동작하는 언어는 C/C++ 정도밖에 없다고 한다.
5. 네이티브 메서드 라이브러리 (Native Method Library)
- C, C++로 작성된 라이브러리
- 만일 헤더가 필요하면 JNI는 이 라이브러리를 로딩하여 실행한다.
참고내용
- https://steady-coding.tistory.com/305
- https://inpa.tistory.com/entry/JAVA-%E2%98%95-JVM-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD-%EC%8B%AC%ED%99%94%ED%8E%B8
- https://coding-factory.tistory.com/828
- https://github.com/backtony/Backend_Interview_for_Beginner/blob/master/Java.md
'정리' 카테고리의 다른 글
[친절한 SQL 튜닝] 인덱스 기본 (1) | 2024.04.21 |
---|---|
[친절한 SQL 튜닝] 데이터 저장 구조 및 I/O 메커니즘 (1) | 2024.02.03 |
[DB] 트랜잭션 정리 (0) | 2023.06.17 |
[DB] Index 정리 (0) | 2023.06.13 |
CORS(Cross-Origin Resource Sharing) 이해와 적용 (1) | 2023.06.08 |