이것저것
JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가? 본문
[JVM이란 무엇인가]
Java Virtual Machine의 약자로, Java Byte Code를 OS에 맞게 해석해주는 역할을 한다. 즉, Java 와 OS 사이에서 중재자와 같은 역할을 하며, Java 가 OS에 구애받지 않고 재사용 가능하도록 해준다.
즉, 어느 OS 에서든 실행시키기 위해서 Java 애플리케이션은 JVM을 거친 이후 OS를 거치게 된다. 그러다 보니, 해당 HW에 맞게 완전히 컴파일된 상태가 아닌 실행 시 해석되기 때문에 속도가 비교적 느리다는 단점을 가진다.
- Java는 직접 실행 가능한 코드가 아닌, Byte Code를 생성
- JVM 이 이 Byte Code를 기계어로 번역 (Interpret)하여 실행
- OS 등 실행환경이 바뀌어도 어디에서든 Java를 실행 가능 (HW 의존성이 낮다.)
- 메모리를 관리하고 Garbage Collection을 수행한다.
[컴파일 하는 방법]
자바 소스 코드 (.java) 는 기본적으로 확장자가 .java인 text 파일 뿐이다. 이 코드를 실행하기 위해선, .java 파일을 컴파일하여 .class Byte Code 파일로 만들어야 한다. 만들어진 .그리고 class 파일을 JVM 이 실행하여 Java 애플리케이션을 작동시킨다.
JDK (Java Development Kit) 를 설치하면 bin 디렉토리 안에 javac라는 Java Compiler가 포함되어 있다. 이를 통해 javac 라는 명령어를 사용하여 자바 파일을 컴파일 할 수 있다.
(추가 : Java 는 기본적으로 상위버전에서 하위버전으로 호환이 유연하다. 그라나, 하위버전 컴파일러에서 상위버전으로 컴파일된 파일은 실행할 수 없다. ex: 11-> 8 컴파일 가능, 8->11 컴파일 불가)
[실행하는 방법]
javac 명령어를 사용하여 .java 파일을 컴파일하여 .class 파일 (Byte Code 파일)을 생성했다면, 이 class 파일을 java 명령어를 통해 실행할 수 있다.
//MyApplication.class 실행
java MyApplication
[바이트 코드란 무엇인가?]
바이트 코드 (Byte Code)란 특정 HW 가 아닌, 가장 컴퓨터에서 돌아가는 실행 프로그램을 위한 "이진 표기법" 이며, 기계가 직접 실행하는 기계어가 아닌 중간 단계의 형태를 뜻한다. SW에 의해 처리되기 때문에, 보통 기계어보다 추상적(?) 이다.
바이트 코드는 특정 HW 에 대한 의존성을 줄이고, 해석하기 쉽게 프로그래밍 언어에 의해 생성되며, 컴파일되어 만들어진 바이트 코드는 특정 HW의 기계 코드를 만드는 컴파일러의 입력으로 사용되거나, Virtual Machine에서 실행된다.
(즉, 해석을 JVM 이 담당하므로, JVM 이 이해할 수 있는 코드이다.)
[JIT 컴파일러란 무엇이면 어떻게 동작하는가?]
JIT는 Just In Time 의 약자로, JIT 컴파일러는 Byte Code를 기계어로 번역하여 실행한다.
보통 컴퓨터 프로그램을 만드는 방법은 (1) 인터프리터 방식, (2) 정적 컴파일 방식 두 가지가 존재한다.
(1) 인터프리터 방식 : 실행 중 프로그래밍 언어를 읽어가며 해당 기능에 대응하는 기계어 코드를 실행한다.
(2) 정적 컴파일 방식 : 실행하기 전에 프로그램 코드를 기계어로 번역한다.
JIT 컴파일러는 위 두가지를 혼재한 방식으로, 실행 시점에서 인터프리터 방식으로 기계어 코드를 생성하고, 해당 코드를 캐싱하여 같은 함수가 다시 호출될 때, 매번 기계어가 생성되는 것을 방지한다.
JVM 에서는 자바 컴파일러가 Byte Code로 변환시킨 후, 실제 Byte Code를 실행하는 시점에서 JVM 이 바이트 코드를 JIT 컴파일러를 통해 기계어로 번역한다.
[JVM 구성요소]
Java 소스 프로그램이 컴파일되어 실행되기까지의 순서를 확인해보면
자바로 프로그램 작성 (.java) -> 컴파일 (.class) -> 프로그램에 실행에 필요한 .class 파일 모두 읽기 -> 메모리 초기화 작업 -> 바이트 코드로 작성된 프로그램을 기계어로 번역 (JIT)
의 과정을 거친다.
JVM은 (1) Class Loader, (2) Garbage Collector, (3) Runtime Data Area, (4) 실행 엔진 4가지로 구성
(1) Class Loader
.class (바이트 코드) 파일을 엮어 Runtime Data Area 형태로 메모리에 적재한다. 내부적으로 로딩, 링크, 초기화 단계가 있고, 초기화 단계에서 전역 변수를 메모리에 할당한다.
(2) Garbage Collector
Heap 메모리 영역에 생성된 객체 중 주소가 사라져 사용할 수 없는 객체를 탐색 후 제거한다.
(3)Runtime Data Area
메모리는 런타임 시 필요한 메모리 영역으로, 스택, 힙, PC 레지스터, 메서드, 네이티브 메서드 스택이 있다.
(4) 실행 엔진 (Execution 엔진)
실행 엔진은 Class Loader에 의해 실행에 필요한 준비과정이 완료된 후, 인터프리터나 JIT 컴파일러를 통해 JVM 메모리 공간에 적재된 Byte Code를 번역하여 실행하는 역할을 한다.
[JDK와 JRE 차이]
JDK
- 자바 애플리케이션 개발 환경으로, JRE, 소스파일의 컴파일러 및 디버거 등 자바 애플리케이션을 개발하기 위한 도구를 포함
- JDK 설치하면 JRE 도 같이 설치
JRE
- 컴파일된 자바 프로그램을 실행시킬 수 있는 자바 환경
- JRE는 JVM이 자바 프로그램을 동작시킬 때 필요한 라이브러리 파일들과 기타 파일 등을 가지고 있다.
- JRE 는 .class 파일을 JVM으로 로딩시키고(Class Loader) , JVM은 .class 파일 해석해 실행할 수 있는 상태로 만든다. (JIT)
'Java' 카테고리의 다른 글
static 변수와 static 메서드 (0) | 2021.05.12 |
---|---|
자바 데이터 타입, 변수 그리고 배열 (0) | 2021.04.26 |
OOP 란? (0) | 2021.04.20 |
가비지 컬렉션(Garbage Collection)이란? (0) | 2021.04.18 |