오늘의 포스팅 목표는 자바 소스 파일(.java)을 JVM으로 실행하는 과정을 이해하는 것입니다.
목차
1. JVM이란 무엇인가
2. 컴파일 하는 방법
3. 실행하는 방법
4. 바이트코드란 무엇인가
5. JIT 컴파일러란 무엇이며 어떻게 동작하는지
6. JVM 구성 요소
7. JDK와 JRE의 차이
1. JVM이란 무엇인가
JVM은 Java Virtual Machine의 줄임말로 자바가상머신이라고도 불립니다.
JVM은 어떠한 환경(운영체제)에서도 자바 프로그램이 실행될 수 있도록 하는 프로그램입니다. 이는 자바의 기본 원칙인 WORA(Write Once, Run Anywhere)을 지키기 위함입니다.
과거에는 같은 프로그램인데도 불구하고 Windows, Mac, Linux 등의 운영체제에 맞게 다르게 작성되었습니다.
JVM이 등장하면서 운영체제별로 종속적이었던 프로그램들이 독립적으로 실행될 수 있게 되었습니다.
2. 컴파일 하는 방법
jdk\bin에 위치한 javac 컴파일러가 자바 코드(.java 파일)를 JVM(자바가상머신)이 이해할 수 있는 형태인 바이트 코드(.class 파일)로 변환합니다.
이클립스나 인텔리제이 등이 존재한다면 알아서 컴파일을 해주지만 그렇지 않다면 컴파일 할 파일이 위치한 폴더까지 이동하여 javac "클래스명.java"를 입력하면 됩니다.
3. 실행하는 방법
2번 처럼 이클립스나 인텔리제이 등이 존재한다면 알아서 실행을 해주지만 이러한 것들이 없다면 cmd 창을 켜서 실행할 자바 소스코드가 있는 폴더까지 이동한 이후 java "클래스명.java"를 입력하면 됩니다.
단, 모든 환경변수가 설정되어 있다는 가정하에 실행됩니다.
4. 바이트 코드란 무엇일까?
바이트 코드는 javac 컴파일러에 의해 JVM이 이해할 수 있는 언어로 변환된 .class 파일을 의미합니다.
.class 파일은 0과 1로만 구성되어 있으며 JVM만 설치되어 있다면 바이트 코드(.class 파일)은 어떠한 운영체제에서도 실행될 수 있습니다. 단, JVM은 운영체제에 종속적이므로 각 운영체제에 맞는 JVM을 설치해야 합니다.
javac 컴파일러에 의해 .java 파일이 .class 파일로 생기는 과정을 도식화 해보았습니다.
이클립스에서 .java 파일을 만들고 저장 버튼을 누르는 순간 내부 동작은 다음과 같습니다.
1. SSD에 JAVA 소스코드가 저장됩니다.
2. javac 컴파일러는 운영체제에 의해 램에 올라갑니다.
3. 램에 위치해 있는 컴파일러는 SSD에 저장된 자바 파일을 읽습니다.
4. 컴파일러는 읽은 자바 파일을 레지스터에다가 조금씩 정보를 보냅니다.
레지스터는 램보다 더 빠르지만 저장 공간이 작기 때문에 컴파일러가 자바 파일을 조금씩 밖에 보내지 못합니다.
5. 레지스터는 컴파일러에게 받은 자바 정보를 CPU와 주고 받습니다.
6. 레지스터는 CPU와 주고받은 정보를 다시 컴파일러에게 보냅니다.
7. 4번부터 6번까지의 과정을 반복하다가 레지스터가 모든 자바파일의 정보를 CPU와 주고받는 작업이 끝나면 컴파일러가 SSD 내부에 .class파일(바이트 코드)를 생성합니다.
5. JIT 컴파일러란 무엇이며 어떻게 동작할까?
다른 언어들과는 달리 자바 언어는 운영체제에 종속되지 않게 하기 위하여 자바 코드를 바이트 코드로 변환하는 과정을 거치게 됩니다.
그래서 자바는 이러한 추가적인 단계를 거치기 때문에 다른 언어보다 CPU에게 전달하는 속도가 느리다곤 합니다.
그런데 이것을 빠르게 하는 기술이 있는데 그것이 바로 JIT(Just In Time) 컴파일러입니다.
JIT 컴파일러는 인터프리터가 해석하는 기계어들 중에 자주 사용되는 코드 부분을 기계어로 캐싱을 하여 또 다시 호출되었을 때, 인터프리터가 해석하는 것이 아닌 JIT 컴파일러가 기계어로 변환해 놓은 캐시에서 꺼내 사용합니다.
다른 언어들에 비해 자바의 속도가 많이 느리다는 말은 옛말일 것 같네요.
JIT 컴파일러는 실행 엔진(Execution Engine) 내부에서 동작합니다.
6. JVM 구성 요소
JVM의 구성요소는 다음과 같습니다.
1. 인터프리터
2. 클래스 로더
3. 실행엔진(내부에 JIT 컴파일러)
4. 가비지 컬렉터
인터프리터는 .class(바이트 코드)를 해당 하드웨어의 환경에 맞게 변환을 하여 운영체제에 종속적인 상태를 종속적이지 않은 상태로 만들어주는 역할을 합니다.
클래스 로더는 컴파일러가 SSD 내부에 만든 .class 파일을 읽습니다. 이러한 행위를 클래스 로드라고 합니다.
실행엔진은 클래스 로더에 존재하는 클래스를 읽으면서 static이 붙어 있는지 없는지 판단을 합니다.
만약에 static이 붙은 클래스가 없다면 자바는 그대로 종료됩니다.
C/C++에서는 free/delete를 통하여 개발자가 직접 메모리 관리를 해야만 했습니다. 하지만 자바에서는 가비지 컬렉터가 더 이상 사용하지 않는 메모리를 자동으로 회수해 갑니다.
7. JDK와 JRE의 차이
JDK는 Java Development Kit의 약자로 자바를 개발하기 위해 만들어 놓은 툴입니다.
개발자들이 개발하기 쉽도록 하는 도구들을 포함합니다(컴파일러 등).
JDK는 JRE를 포함합니다.
JRE는 Java Runtime Environment의 약자로 자바를 실행할 수 있는 실행환경이 들어있습니다.
JRE는 JVM을 포함합니다.
'Programming > Java' 카테고리의 다른 글
[Java] try-with-resources 구문을 사용하여 할당한 자원을 자동으로 해제하기 (0) | 2021.08.01 |
---|---|
[Java] 제네릭(Generic) 타입이란? (0) | 2021.06.14 |
[Java] 래퍼 클래스와 박싱, 언박싱에 대해 알아보자 (1) | 2020.10.28 |
[Java] 제네릭(Generic)을 예시를 통해 알아보자 (0) | 2020.10.24 |
[Java] 인터페이스에 대해 알아보자 (0) | 2020.10.17 |