▣ 목표
자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기.
▣ 학습할 내용
- JVM이란 무엇인가
- 컴파일하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는지
- JVM 구성 요소
- JDK와 JRE의 차이
▶ 1-1 JVM이란 무엇인가?
Java Virtual Machine(JVM)은 자바 가상 머신이라고도 불리며 JVM이 있기 때문에 자바로 작성된 모든 애플리케이션을 OS 종류에 구애받지 않고 개발할 수 있다. 일반적인 애플리케이션 코드는 OS를 거쳐 하드웨어에 전달되었지만, Java는 JVM을 한 단계 더 거치기 때문에 C언어 등에 비해 상대적으로 느리다는 단점이 있었지만, 지속적으로 개선된 사항과 최근 JIT 컴파일러의 역할을 보면 향상된 최적화 기술이 적용되어 속도 격차가 많이 줄었다. JIT 컴파일러 내용은 아래에서 자세히 :-)
▶ 1-2 컴파일하는 방법
(환경변수가 설정된 상태일 경우) 위와 같이 명령어를 수행하면 해당 소스파일이 컴파일되고 .class 확장자의 파일이 생성된다.
javap -c 파일명.class을 수행하면 해석된 바이트코드를 볼 수 있다.
▶ 1-3 실행하는 방법
Java로 소스파일(확장자: .java)을 작성한다.
→ 작성된 소스파일은 javac 컴파일러를 통해 바이트코드로 컴파일된다.(확장자 : .class)
→ 컴파일된 .class파일을 명령어 또는 IDE에서 실행한다.
▶ 1-4 바이트코드란 무엇인가?
(Java의) 바이트코드란, JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미한다. 컴파일러에 의해 변환되는 코드의 명령어 크기가 1바이트라서 바이트코드로 불린다. 확장자는 .class이며, JVM만 설치되어 있다면, 어떤 운영체제에서도 실행될 수 있다.
▶ 1-5 JIT 컴파일러란 무엇이며 어떻게 동작하는지
인터프리터를 통해서 읽혀진 바이트코드는 *native코드로 변환되어 기계가 실행할 수 있는 형태로 변경된다. 이때 특정 영역의 코드가 자주 읽히게 되면 그 영역을 hot code영역이라고 부르고 이 영역을 좀 더 효율적으로 다루기 위해 등장한 컴파일러가 JIT 컴파일러(Just-in-Time Compiler)다. 단순한 native코드로의 변환이 아니라 최적화된 native코드를 얻어낸다. 이렇게 컴파일된 native코드를 캐싱하고 이후 캐싱된 코드를 제외하고 컴파일하게 되어 속도를 개선시킬 수 있다.
* native코드란?
CPU와 운영체제가 직접 실행할 수 있는 코드를 의미한다. (자바 소스코드는 바이트코드로 컴파일된 후 native코드로 한번 더 컴파일되어 기계가 실행할 수 있는 상태가 된다. )
▶ 1-6 JVM의 구성요소
Class Loader
모든 JVM에는 class loader가 포함되어 있다. 자바 애플리케이션을 실행하기 위해서는 컴파일된 바이너리 파일을 JVM에 로드하고 링크를 통해 배치해야 한다. JVM의 Execution Engine이 사용할 수 있도록 Runtime Data Area에 적재하는 역할을 한다.
Execution Engine
클래스를 실행하는 역할을 한다. 메모리에 배치된 바이너리 파일을 실제 JVM내부에서 기계가 실행할 수 있는 형태로 변경한다. 변경하는 방법은 위에서 설명한 인터프리터 방식과 JIT 방식이 있다. 명령어를 한 줄씩 해석해서 실행하는 인터프리터 방식과 인터프리터의 단점을 보완하는 JIT컴파일 방식이 있다.
Runtime Data Areas
런타임 데이터 영역은 프로그램 수행을 위해 OS에서 할당받는 메모리 영역이다. 런타임 영역은 5개로 나뉜다.
- 이중 PC 레지스터(PC Register)
- JVM stack
- Native Method Stack
- Heap
- Method Area
PC Register, JVM 스택, 네이티브 메서드 스택은 스레드마다 하나씩 생성되며, 힙과 메서드 영역은 모든 스레드가 공유해서 사용한다.
- 이중 PC 레지스터(PC Register)
스레드가 시작될 때 생성된다. 스레드가 어떤 명령어로 실행되어야 할 지에 대한 기록을 하는 부분으로 현재 수행 중인 JVM명령의 주소를 갖는다.
- JVM stack
프로그램 실행 과정에서 임시로 할당되었다가 메서드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역이다. 지역변수, 매개변수, 메서드 정보, 연산 중 발생하는 임시 데이터 등이 저장 대상이 된다. 메서드 호출 시마다 각각의 스택 프레임(해당 메서드만을 위한 공간)이 생성된다. 메서드 실행이 끝나면 프레임 별로 삭제된다.
- Native Method Stack
일반적으로 JVM은 네이티브 방식을 지원한다. 따라서 스레드에서 네이티브 방식의 메서드가 실행되는 경우 Native Method Stack에 쌓인다. 일반적 메서드를 실행하는 경우 JVM 스택에 쌓이다가 해당 메서드 내부에 네이티브 방식을 사용하는 메서드(예-C언어로 작성된 메서드)가 있다면 해당 메서드는 네이티브 스택에 쌓인다.
- Heap
동적으로 할당되는 데이터가 저장되는 영역이다. 객체, 배열 등이 생성되었을 때 저장되는 공간이다. Heap에 할당된 데이터는 Garbage Collecting 대상이다. JVM 성능 관련하여 가장 많이 언급되는 공간이다.
- Method Area
Class Area, Code Area, Static Area 등으로 불린다. 메서드 영역은 모든 스레드가 공유하는 영역으로 JVM이 시작될 때 생성된다. JVM이 읽어 들인 각각의 클래스와 인터페이스에 대한 Runtime Constant Pool, field, method code, static variable, 메서드의 바이트코드 등을 보관한다.
- Runtime Constant Pool
Method Area 내부에 존재하는 영역으로, 각 클래스와 인터페이스의 상수뿐만 아니라 메서드와 필드에 대한 모든 레퍼런스까지 담고 있는 테이블이다. 즉, 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.
▶ 1-7 JDK와 JRE의 차이?
JRE는 자바 실행환경(Java Runtime Environment)의 약자이다. JVM이 자바 프로그램을 작동시킬 때 필요한 라이브러리 파일들과 그 외 관련된 파일들을 가지고 있다. (실행 OK, 개발 X)
JDK는 자바 개발도구(Java Development Kit)의 약자로 JRE와 개발에 필요한 도구(javac, java등)들을 포함한다. (실행 OK, 개발 OK)
백기선님의 자바 라이브 스터디 커리큘럼을 따라 공부하고 있습니다.
잘못된 점이나 보충할 부분이 있으면 코멘트 남겨주세요
작은 조언이 저에겐 성장의 원동력이 됩니다 :-)
'Java' 카테고리의 다른 글
[자바 스터디] #9 - 예외처리 (0) | 2021.02.18 |
---|---|
[자바 스터디] #7 - 패키지 (0) | 2021.02.17 |
[자바 스터디] #8 - 인터페이스 (1) | 2021.02.16 |
[자바 스터디] #3 - 연산자 (0) | 2021.02.04 |
[자바 스터디] #2 - 데이터 타입, 변수 그리고 배열 (0) | 2021.01.27 |
댓글