JVM이란
◆ Java Virtual Machine의 줄임말
◆ Java Byte Code를 OS에 맞게 해석해주는 역할
* Java Byte Code : 자바 가상 머신이 이해할 수 있는 언어로 변환된 자바 소스 코드, 자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1바이트
※ 프로그램 실행구조 비교
- 일반 프로그램은 "운영체제"가 프로그램을 실행. 반면 Java 프로그램은 운영체제가 JVM을 실행시키면 "JVM"이 프로그램(클래스 파일)을 실행
- Java 프로그램의 클래스 파일들은 운영체제에서 직접 동작하는 것이 아니라 "JVM"위에서 동작
* 즉, Java 프로그램은 한 번 만들기만 하면 Windows, Linux, Mac 어느 운영체제든 실행 가능 ( = 플랫폼 독립성, 이식성↑)
Java compiler는 .java파일을 .class라는 Java byte code로 변환
* Byte 코드는 기계어가 아니기 때문에 OS에서 바로 실행이 안됨
JVM은 OS가 Byte code를 이해할 수 있도록 해석하는 과정이 필요
- 장점 : JIT(Just In Time)컴파일러를 구현
* JIT 컴파일 방식 : Byte code를 런타임 시점에 바로 기계어로 변환, 즉 전체 Byte code를 컴파일하고 캐시에 보관
- 단점 : c언어와 같은 네이티브 언어에 비해 속도가 느림
자바 가상 머신의 구성
JVM은 Garbage Collector, Class Loader, Execution Engine, Runtime Data Areas로 구성되어 있음
● Garbage Collector
때에 따라 Garbage Collector가 메모리 관리 기능을 자동으로 수행(더 이상 사용되지 않는 객체를 해제시켜 메모리를 자동으로 반납)
● Class Loader
- 런타임시 클래스 파일들을 JVM 내부로 로딩, 분석한 뒤에 각각 런타임 영역에 배치
- Java는 동적으로 클래스를 읽어오기 때문에 런타임 시점에서야 모든 코드가 JVM과 연결
● Execution Engine
런타임 데이터 영역에 배치된 Byte code를 해석하며 실행. 이 때 인터프리터 방식과 JIT 컴파일 방식을 혼합하여 해석
* 인터프리터 방식 : Byte code를 한 줄씩 읽고 해석
* JIT 컴파일 방식 : Byte code를 런타임 시점에 바로 기계어로 변환
※ 최초의 가상 머신은 인터프리터 방식만 써서 실행 속도가 느렸지만, JIT 컴파일 방식을 추가하여 이를 보완하고자 했음
> 그런데 JIT 컴파일은 Byte code를 기계어로 바꾸기 때문에 실행 속도가 빠르지만 변환하는 데 비용이 발생
> 그래서 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일 방식으로 실행
● Runtime Data Areas
- 클래스 로더에서 분석된 클래스 파일의 데이터를 저장하고 실행 도중에 필요한 데이터를 저장
- 메모리를 효율적으로 관리하기 위해 크게 5개의 영역(메서드, 힙, 스택, PC레지스터, 네이티브 메서드 스택)으로 구분하며, 간단히 메모리 영역이라고 부름
※ 메모리 영역
1. 메서드
1) 용도
- 가장 먼저 데이터가 저장되는 공간
- Class Loader에 의해 로딩된 클래스, 메서드, static, 전역변수가 저장
- static이나 전역변수를 무분별하게 많이 사용하면 메모리 부족현상 발생
2) 보존기간
- 프로그램의 시작부터 종료까지 메모리에 남음
- 명시적인 Null 선언시 Garbage Collector 청소대상
2. 힙
1) 용도
- 런타임 시 결정되는 참조형 데이터 타입이 저장되는 공간
* 참조형 데이터 : 기본형을 제외한 나머지(String, StringBuffer, List 등 개인이 만든 클래스도 참조형 데이터)
- new 연산자를 통해 생성된 객체가 저장되는 공간
2) 보존기간
- 객체가 더 이상 쓰이지 않거나, 명시적인 Null 선언시 Garbage Collector 청소대상
3. 스택
1) 용도
- 컴파일 시 결정되는 기본형 데이터 타입이 저장되는 공간
- 지역변수, 매개변수, 리턴값, 참조변수 등이 저장
- 메서드 호출될 때, 메모리에 FILO(First-In Last-Out)로 하나씩 생성
- 메서드 끝날 때, 메모리에 LIFO(Last-In First-Out)로 하나씩 제거
- 메서드 호출시마다 각각의 스택프레임이 생성
* 스택프레임 : 함수가 호출될 때, 그 함수만의 스택 영역을 구분하기 위해 생성되는 공간
2) 보존기간
- { } 또는 메서드가 끝날 때 까지(끝날 때는 프레임별로 삭제)
4. PC 레지스터
1) 용도
- JVM이 수행 할 명령어의 주소를 저장하는 공간
2) 보존기간
- 스레드가 시작될 때 마다 생성
5. 네이티브 메서드 스택
1) 용도
- Byte code가 아닌, 기계어로 작성된 코드를 실행하는 공간
- 다른 언어(C/C++)로 작성된 코드를 수행하기 위함
- Java Native Interface를 통해 Byte code로 변환됨
* JNI(Java Native Interface) : Java로 C와 C++ 등의 코드를 실행시키는 인터페이스
2) 보존기간
- Java Native Interface 호출 및 종료 시 생성
※ 1~2는 모든 스레드 공유
※ 3~5는 각 스레드별로 생성
JDK와 JRE의 차이
JDK(Java Development Kit)
◆ Java를 사용하기 위해 필요한 모든 기능을 갖춘 Java용 SDK
◆ JRE에 있는 모든 것들을 포함하고 있으며, 컴파일러(javac)와 jdb, javadoc과 같은 도구도 있음
> 즉, JDK는 프로그램을 생성하고 컴파일할 수 있음
JRE(Java Runtime Environment)
◆ JVM(자바 가상 머신), 자바 클래스 라이브러리, 자바 명령(Java Command) 및 기타 인프라를 포함한 컴파일된 Java 프로그램을 실행하는데 필요한 패키지
※ JDK를 설치할 때 JRE도 같이 설치가 됨
※ Java 프로그램을 실행하기만 한다면 JRE만 설치해도 무방하지만 Java 프로그래밍을 한다면 JDK를 설치해야 함