-
1. JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가Java 2020. 11. 11. 17:05
목표
자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기.
학습할 것
- JVM이란 무엇인가
- 컴파일 하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는지
- JVM 구성 요소
- JDK와 JRE의 차이
1. JVM이란 무엇인가
(Java Virtual Machine, 자바 가상머신)
Java로 개발한 프로그램을 컴파일하여 만들어지는 바이트코드를 실행시키기 위한 가상머신이다.
JRE (Java Runtime Environment)에 포함되어 있으며, Java 컴파일러가 프론트엔드를 담당한다면 JVM은 코드 최적화와 백엔드를 담당한다.
Java 소스 코드는 javac 컴파일러를 거쳐 바이트코드로 변환되며, 이 바이트코드는 JRE에 들어있는 java classloader에 의해 JVM으로 적재되고 JVM은 적재된 바이트코드를 JIT 컴파일 방식으로 실행한다.
JVM은 플랫폼 독립적으로, JVM이 실행 가능한 환경이라면 어디서든 Java 프로그램이 실행될 수 있도록 한다.
즉, Java의 모토인 Write once, Run anywhere은 JVM을 통해 가능한 것이다.
하지만 특정 운영체제의 특수한 기능을 호출하거나 하드웨어를 제어하는 등의 일은 JVM으로 할 수 없으며,
JNI 같은 Native 코드를 호출하기 위한 인터페이스를 거쳐야 한다.
JVM 이라고 해서 Java 바이트코드만 인식하는 것은 아니다. 이 바이트코드를 Java가 아닌 다른 언어들을 가지고도 생성할 수 있기 때문이다. 따라서 지금의 JVM은 Java만을 위한 것이라고 생각하면 안 된다.
2. 컴파일 하는 방법
- 컴파일이라고 하면 어떤 언어로 된 소스 코드를 기계가 인식할 수 있는 네이티브 코드로 변환하는 과정을 의미하지만,
자바에서의 컴파일은 자바 언어로 된 코드를 JVM이 인식 할 수 있는 JVM 명령어 코드 (바이트코드)로 변환하는 것을 의미한다.
드물지만 자바에서의 컴파일도 일반적인 의미의 컴파일처럼 기계가 인식할 수 있는 코드로 변환하는 과정을 의미할 때도 있다.
대표적으로 JIT 컴파일러가 하는 컴파일은 바이트코드로 변환하는 것이 아니라 바이트코드를 네이티브 코드로 변환하는것을 의미한다.
- 자바 코드를 자바 언어 스펙에 따라 분석/검증하고, JVM 스펙의 class 파일 구조에 맞는 바이트코드를 만들어내는 과정
javac.exe
- 자바 컴파일러 : 자바 소스코드를 바이트코드로 컴파일
java.exe
- 자바 인터프리터 : 컴파일러로 생성된 바이트코드를 해석하고 실행
javap.exe
- 역 어셈블러 : 컴파일된 클래스파일을 원래의 소스로 변환
jar.exe
- 압축 : 자바프로젝트를 실행시키기 위한 파일들을 압축
javadoc.exe
- 문서화 : 자바파일에 있는 주석들을 문서화
자바 소스 코드 파일(.java) -> javac 컴파일러 -> JVM 바이트코드(.class)
- javac 파일명
3. 실행하는 방법
1. 자바 컴파일러를 통해 (.java) 파일을 자바 바이트코드 (.class)로 변환한다.
2. 클래스로더를 통해 자바 바이트코드를 런타임 데이터 영역에 로드한다.
3. 실행엔진을 통해서 실행한다.
- java 파일명
4. 바이트코드란 무엇인가
- 자바 컴파일러에 의해 JVM이 이해할 수 있는 언어로 변환된 .class 파일을 말한다.
- 명령어의 크기가 1 바이트라서 바이트코드라 불린다.
JVM만 설치되어 있다면 바이트코드는 어떠한 운영체제에서도 실행될 수 있다.
단, JVM은 운영체제에 종속적이므로 각 운영체제에 맞는 JVM을 설치해야 한다.
5. JIT 컴파일러란 무엇이며 어떻게 동작하는지
다른 언어들과는 달리 자바 언어는 운영체제에 종속되지 않게 하기 위하여 자바 코드를 바이트 코드로 변환하는 과정을 거치게 된다.
이러한 추가적인 단계를 거치기 때문에 다른 언어보다 속도가 느리다.
이것을 빠르게 하는 기술이 JIT(Just In Time) 컴파일러 (프로그램을 실제 실행하는 시점에 번역하는 컴파일 기법)이다.
같은 코드를 매번 해석하지 않고 실행할 때 컴파일 하면서 코드를 캐싱하여, 같은 함수가 다시 호출될때 매번 기계어가 생성되는 것을 방지하여 속도가 빠르다.
- JVM은 JIT 컴파일러를 지원한다.
바이트코드가 실행되는 시점에서 가상 머신이 바이트코드를 JIT 컴파일러를 통해 기계어로 변환한다.
6. JVM 구성 요소
1. Class Loader
- JVM 내로 클래스를 로드하고 링크를 통해 배치하는 작업을 수행하는 모듈이다.
Runtime시에 동적으로 클래스를 로드하며, jar 파일 내에 저장된 클래스들을 JVM위에 탑재하고 사용하지 않는 클래스들은 메모리에서 삭제한다.
2. Execution Engine
- 두 가지 방식을 이용하여 데이터 영역에 배치된 바이트코드를 실행한다.
인터프리터 : 바이트코드 명령어를 하나씩 읽어서 해석하고 실행한다.
JIT compiler : 인터프리터 방식에 캐싱 방식을 더해 빠르게 수행한다.
3. Runtime Date Area
- 프로그램 수행을 위해 OS에서 할당받은 공간
PC 레지스터, 스택, 네이티브 메서드 스택은 스레드마다 하나씩 생성되고 힙, 메서드 영역은 모든 스레드가 공유해서 사용한다.
Heap
- 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 메모리 영역.
New 연산를 통해 생성한 객체, 인스턴스를 저장하는 공간으로, 가비지 컬렉션 대상이다.
Method
- 클래스, 인터페이스, 필드, 메서드, Static 변수, 바이트코드 등을 보관한다.
PC Register
- 현재 수행중인 JVM 명령의 주소를 갖는다.
어떤 부분을 어떤 명령으로 실행할지를 기록하며 현재 명령과 주소를 저장한다.
Stack
- 메서드 호출 시 생성되는 스레드 수행 정보를 기록한다.
임시 데이터를 저장한다.
Native Method Stack
- 자바 외의 언어로 작성된 네이티브 코드를 위한 스택이다.
JNI (Java Native Interface)를 통해 호출하는 코드를 수행하기 위한 스택이다.
7. JDK와 JRE의 차이
JDK (Java Development Kit) 은 자바 통합 개발 환경을 의미한다.
JRE (Java Runtime Environment) 는 자바 실행 환경을 의미하며 JDK에 속해있다.
※ 출처
www.notion.so/1-JVM-23303b33468a4c49bace6ee71839aecd
blog.naver.com/pond1029/222141054404
* 스터디
'Java' 카테고리의 다른 글
3. 연산자 (0) 2020.11.28 2. 자바 데이터 타입, 변수 그리고 배열 (0) 2020.11.25 BufferedReader , BufferedWriter (0) 2020.08.28 java - 14 ) 컬렉션 프레임워크 (2) 2020.08.28 java - 12 ) 자바 API 클래스 (0) 2020.08.03