- JVM(Java Virtual Machine)
: 자바 가상 머신, 스택 기반 머신
: 자바 프로그램을 실행하고 다른 언어로 작성된 것도 Java byte code로 컴파일 하여 실행할 수 있도록 만들어 짐
: JVM은 OS 상관 없이 어느 환경에서도 Java가 실행이 되도록 만들어 짐
- 기술적 정의: JVM은 코드를 실행하고 해당 코드에 대해 런타임 환경을 제공하는 소프트웨어 프로그램에 대한 사양(Specification)이다.
- 일반적 정의: JVM은 자바 프로그램을 실행하는 방법이다. JVM의 설정을 구성한 다음 설정사항에 따라 실행 중에 프로그램 리소스를 관리한다.
- 자바의 작동 방식
: Java는 기본적으로 Write once, Run anywhere 을 기반으로 함 (한번 쓴 것은 어디서든지 읽혀야 함)
: Java는 Javac(Java Complier)을 이용하여 .java 파일을 .class 파일인 Byte code로 컴파일 해줌
: 이 Byte code는 JVM에 의해서 OS와 하드웨어가 이해할 수 있는 기계어로 변환 됨(interpret)
: 즉 OS나 CPU 구조에 상관없이 JVM을 해당 OS에 맞게 다른환경의 Byte code를 읽어올 수 있음
# Binary code : 기계가 읽을 수 있는 이진 코드
# Byte code : 가상 머신이 읽을 수 있는 이진 코드(JVM을 위해 만들어짐)
- 구조
- JRE (Java Runtime Enviroment)
: 자바 코드를 실행하기 위한 환경
: JVM + 핵심 라이브러리
: 개발 관련 X, 실행 관련 o
: Java는 보동 JRE 단위로 배포됨
- JDK (Java Development kit)
: 자바 기반의 소프트웨어를 개발하기 위한 도구
: JRE + 개발 툴(Java c)
- JVM 구조
1. Class Loader SubSystem
: Byte code를 읽어오며 메모리에 적절히 배치하는 역할
: 자바 프로그램은 클래스들로 이루어져 있음
: .java 파일을 javac로 컴파일 하면 바이트코드(.class)가 나옴
: 이 파일을 컴파일 타임이 아닌 런타임에 동적으로 메모리를 올려 실행하는 부분이 Class Loader임
: 런타임 될떄 loads(적재), links(연결), initialises(초기화)를 함
: 컴파일 된 class 파일이 실행되는 순서는 5가지로 이루어짐
1. Load : 컴파일 된 클래스를 메모리에 적재하는 일임 (메모리로 로딩)
2. Verify : 안전성 검증, .class 파일의 정확성을 확인해야 함(유효한 컴파일러, 언어 등) 메모리 연결 유무 검토
3. Prepare : JVM에 의한 데이터 구조나 Static 저장 공간을 위해 메모리를 할당
4. Resolve : 세밀한 메모리의 처리를 담당, 실제 객체의 주소를 참조
5. Initialize : class 파일에서 지정된 클래스 변수를 할당하는 작업을 진행, 초기화 로직
2. Runtime Data Area
: JVM 프로그램이 OS에서 실행이 될 때 메모리에 지정된 영역임
: 힙, 메소드는 전체 공유 자원으로 분류되고
: 스택, PC(Program Counter), 네이티브 메소드 스택은 쓰레드 단위의 자원으로 구분됨
- 메소드
- 클래스 수준의 정보를 저장
- 클래스 이름, 부모 클래스 이름, 메소드, 변수 등
- static 변수, 일반 변수 등
- 클래스 수준의 정보를 저장
- 힙
- 객체(인스턴스) 수준의 정보를 저장
- 스택
- 인스턴스 및 지역 변수의 참조 주소 들을 저장.
- 쓰레드마다 런타임 스택을 만들고, 스택 프레임(메소드 call)을 쌓는다.
- 에러 났을 때, 에러 메시지보면, 런타임 스택에 메시지 쌓여있는걸 확인할 수 있음.
- PC
- 쓰레드마다 가지고 있는 Program Counter.
- 현재 실행할 부분을 가르키고 있다.
- 네이티브 메소드 스택
- 네이티브(native) 메소드 호출할 때 사용하는 별도의 스택
- 네이티브 메소드는 java 가 아닌 c와 같은 언어(low-level) 로 구현된 메소드임.
- 대표적인 예시로, Thread.currentThread() 임.
public static native Thread currentThread() 로 선언되어 있음.
- 대표적인 예시로, Thread.currentThread() 임.
3. Execution Engine
: Class Loader에 의해 메모리에 로딩된 후에 Execution Engine이 주도함
: class 파일을 해석을 주로 함
- 인터프리터
- 바이트 코드를 한줄 한줄 읽어서 네이티브 코드로 변환
- JIT (Just In Time) 컴파일러
- 바이트 코드에서 반복되는 코드 부분은 JIT 컴파일러가 미리 네이티브 코드로 변환 시켜놓음.
- 반복되는 코드가 읽힐 순서가 왔을 때, 인터프리터로 읽지않고 바로 네이티브 코드를 바로 사용한다.
- 인터프리터 읽을 때의 속도 효율성을 JIT 컴파일러가 보완하는 형태.
- GC (Garbage Collector)
- 더 이상 참조되지 않는 객체를 모아서 메모리 정리를 한다.
- 경우에 따라 성능 효율을 위해 커스터마이징을 해야함.
4. Java Native Interface(JNI)
: C, C++로 쓰인 Native Libraries을 제공하는 Native Method Libraries와 상호작용하기 위해서 존재
참고
http://www.itworld.co.kr/news/110837
https://yeon-kr.tistory.com/112?category=857330
https://dailyheumsi.tistory.com/196