JVM(Java Virtual Machine)

Sundae·2023년 10월 25일
0
post-thumbnail

JVM이란?


JVM은 자바 바이트 코드를 운영체제가 인식할 수 있도록 해석해주는 소프트웨어이다.

JVM을 실행시킬 수 있는 환경이면 Java 어플리케이션을 실행 시킬 수 있다는 특징이 있다.

위의 이미지를 보면 일반 애플리케이션은 OS와 바로 붙어 있기 때문에 OS에 종속적이다. 그래서 다른 OS에서 실행시키기 위해선 애플리케이션을 그 OS에 맞게 변경해야 한다.
이에 반해, Java 애플리케이션은 OS가 아닌 JVM하고만 상호작용을 하기 때문에 OS 독립적이라 할 수 있다. 따라서, Java 어플리케이션은 OS에 맞는 JVM만 존재한다면 OS가 달라도 실행할 수 있다.

Java 프로그램이 실행되는 과정


개발자에 의해 작성된 원시코드(.java 확장자)파일은 OS가 알지 못하므로 기계어로 변환해야한다. 우선, 기계어로 변환하기 전에 위 그림과 같이 java 소스 코드는 javac 컴파일러를 거쳐 자바 바이트 코드(.class)로 변환된다. ( 자바 컴파일러 javac.exe는 JDK 내에 존재한다. )

Class Loader


이 후, Class Loader가 JVM으로 클래스 파일을 로드한다. Runtime 시에 로드된 클래스를 동적으로 메모리에 적재한다. 뿐만 아니라, 흩어져있는 클래스 파일들을 가져오고 검증하고 Static 변수들을 초기화하는 역할을 맡는다.

Runtime Data Area


Runtime Data Area 는 JVM이 사용하는 메모리 공간이다. Java 프로그램의 실행 중에 필요한 데이터를 저장하고 관리한다.
Runtime Data Area는 여러 구역으로 나뉘며 구역마다 하는 역할은 다음과 같다.

- Method area

클래스 정보, 스태틱 변수, 상수, 메소드 정보 등의 클래스 정보가 저장되며, Method Area는 모든 스레드가 공유하는 공간으로, 클래스가 메모리에 로드될 때 초기화된다.

- Heap area

객체 인스턴스와 배열이 저장되는 곳이다. 프로그램 실행 중 동적으로 생성되는 인스턴스는 모두 이곳에 생성된다. new 키워드로 생성된 주소에 대한 값 혹은 배열이 생성되는 영역이라 볼 수 있다. 가비지 컬렉터의 대상이며, 더 이상 참조되지 않는 객체는 가비지 컬렉터에 의해 정리된다.

- Stack Area

각 스레드마다 별도로 생성되는 영역으로, 메소드 호출과 관련된 데이터를 저장한다. 지역 변수, 메소드 호출 및 반환 데이터, 스레드 실행 시의 정보가 여기에 저장된다.
스택 프레임이라고도 불리며, 스택 프레임은 메소드 호출 시마다 생성되고 삭제된다. 즉, 메서드가 호출되면, 스택에 메서드를 위한 메모리가 할당되며, 이 후, 메서드가 작업을 마치면 할당되었던 메모리 공간은 비워지게된다.

- PC register

각 스레드마다 별도로 생성되는 영역으로, 현재 실행 중인 JVM 명령의 주소를 저장한다. 스레드가 다음에 실행할 명령의 주소를 가리키는 역할을 한다.

- Native method stacks

JAVA가 아닌 다른 언어로 작성된 코드를 위한 공간. Java Native Interface를 통해 바이트 코드로 전환하여 저장하게 된다.

Execution Engine


Execution Engine은 JVM의 핵심 구성 요소 중 하나로, 자바 바이트 코드를 실행하는 역할을 맡는다. Execution Engine은 자바 바이트 코드를 기계어로 번역하거나 직접 실행하는 역할을 담당한다. Execution Engine의 구성 요소는 다음과 같다.

- Interpreter

Interpreter는 바이트 코드를 순차적으로 읽어들이고 실행한다. 반복적으로 실행이 된다면, 매번 해석하고 수행해야하기 때문에 성능저하가 발생한다.

- JIT(Just-In-Time) Compiler

위의 Interpreter의 단점을 보완하기 위해 도입된 방식이다. JIT compiler는 반복되는 코드를 발견하여 바이트 코드 전체를 Native Code로 변환하여 실행한다. 이후에는 해당 코드들을 더 이상 인터프리터를 사용하지 않고 캐시에 보관해둔 뒤 네이티브 코드로 직접 수행한다.
인터프리터를 사용하여 실행하는것이 아닌, 컴파일된 네이티브 코드를 실행하는 것이기 때문에 수행 속도는 인터프리터 방식보다 빠르게 수행한다.
따라서, JVM은 내부에서 해당 메소드의 수행빈도를 확인 후 반복이 일정 정도를 넘을 때 JIT Compile 방식을 수행한다.

- Garbage Collector

Garbage Collector는 Heap 메모리 영역에서 더는 사용하지 않는 메모리를 식별하고 자동으로 회수해 준다. 이를 통해 메모리 누수를 방지하며 자바 프로그램의 안정성과 성능을 유지한다. C언어에선 개발자가 메모리를 직접 해제해주어야한다. 반면 Java는 Garbage Collector를 이용하여 자동으로 메모리를 비워주기 때문에 더욱 편리한 프로그래밍이 가능하다.




profile
성장 기록 / 글에 오류가 있다면 댓글 부탁드립니다.

0개의 댓글