JVM(Java Virtual Machine)이란?
JVM(Java Virtual Machine)이란 자바 가상 머신의 약자를 줄여 부르는 용어이다. 자바 프로그램은 JVM을 사용하여 프로그램을 실행한다. 일반적 프로그램들은 OS위에서 실행되지만 자바 프로그램 같은 경우는 OS 위의 JVM에서 실행된다. 왜그럴까?
-> 자바 프로그램을 OS 종류에 상관없이 실행시키기 위함이다. 예를 들자면 Windows에서 동작하도록 구현된 프로그램은 Linux에서는 동작하지 않는다. 자바 프로그램은 OS 종류에 관계 없이 그에 맞는 JVM을 다운로드하여 자바 프로그램을 실행 시킬 수 있다. 즉 JAVA와 OS 사이에서 JVM이 중개자 역할을 수행하는 것이다.
또 JVM은 메모리 관리, Garbage collection을 수행한다. 그리고 JVM은 스택기반의 가상머신이다. 하드웨어 레지스터 기반으로 동작하는 ARM 아키텍쳐 같은 하드웨어와 달리 JVM은 스택 기반으로 동작한다.
JVM의 역할
- 자바 애플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행
- JAVA와 OS 사이에서 중개자 역할을 수행, OS의 메모리 영역에 직접적으로 접근하지 않고 JVM이라는 가상 머신을 이용하여 간접적으로 접근한다.
- 프로그램의 메모리 관리를 알아서 해준다. C프로그램의 경우 직접 메모리 할당과 해지가 필요하지만 자바에서는 JVM이 자동으로 메로리 관리를 해준다.
JAVA 프로그램 실행 과정
1. 프로그램이 실행되면 JVM은 OS로부터 이 프로그램이 필요로 하는 메모리를 할당받는다.
JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어들여 자바 바이트코드(.class)로 변환시킨다.
3. Class Loader를 통해 class파일들을 JVM으로 로딩한다.
4. 로딩된 class파일들은 Execution engine을 통해 해석된다.
5. 해석된 바이트코드는 Runtime Data Areas 에 배치되어 실질적인 수행이 이루어지게 된다.
이러한 실행과정 속에서 JVM은 필요에 따라 Thread Synchronization과 GC(Garbage collection)같은 관리작업을 수행 한다.

JVM 구성
Java Compiler(javac)
자바 소스코드(.java)를 읽어들여 자바 바이트코드(.class)로 변환
Class Loader(클래스 로더)
JVM내로 클래스(.class파일)를 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈, Runtime 시에 동적으로 클래스를 로드한다. jar 파일 내 저장된 클래스들을 JVM 위에 탑재하고 사용하지 않는 클래스들은 메모리에서 삭제한다. 자바는 컴파일 타임이아니라 런타임에 참조하기 때문에 클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링크하는 것을 클래스 로더가 수행한다.
JAVA 바이트 코드를 읽어 JVM의 Execution Engine이 사용할 수 있도록 Runtime Data Area에 적재.
Excution Engine(실행 엔진)
클래스를 실행시키는 역할, 클래스 로더가 JVM 내의 런타임 데이터 영역에 바이트 코드를 배치시킨 것을 실행 엔진이 실행한다. 자바 바이트 코드는 기계가 바로 수행할 수 있는 언어보다는 비교적 인간이 보기 편한 형태로 기술된 것인데, 실행 엔진은 이와 같은 바이트 코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경하는 역할을 한다.
이때 2가지 방식을 사용한다.
- Interpreter : 명령어를 그때그때 해석해서 실행 -> 한 줄 씩 수행하기 때문에 느리다는 단점이 있다.
- JIT(Just-In-time) : 인터프리터의 단점을 보완하기 위해 도입된 컴파일러, 인터프리터 방식으로 실행하다가 적절한 시점에서 바이트 코드 전체를 컴파일하여 네이티브 코드로 변경하고 이후, 더 이상 인터프리팅 하지 않고 네이티브 코드로 직접 실행하는 방식이다. 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행하게 된다.
물론 JIT컴파일러가 컴파일하는 과정은 바이트코드를 인터프리팅하는 것보다 훨씬 오래걸리므로 한 번만 실행되는 코드라면 컴파일하지 않고 인터프리팅하는 것이 유리하다. 따라서 JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 정도를 넘을 때에만 컴파일을 수행한다.
Runtime Data Area(JVM Memory)
프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간

- PC Register
PC는 Program Counter의 축약어이다. Thread가 시작될 때 생성되고 생성될 때마다 생성되는 공간, Thread마다 하나씩 존재한다. Thread가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분이며 현재 수행 중인 JVM 명령의 주소를 갖는다.
- JVM Stack
프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역, 각종 형태의 변수나 임시 데이터, 스레드나 메소드의 정보를 저장
메소드 호출 시마다 각각의 스택 프레임이 생성된다. 메서드 수행이 끝나면 프레임 별로 삭제를 한다. 메소드 안에서 사용되는 값들(로컬 변수)을 저장한다. 또 호출된 메소드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장한다.
- Native method stacks
일반적으로 JVM은 네이티브 방식을 지원한다. 따라서 스레드에서 네이티브 방식의 메소드가 실행되는 경우 Native Method Stacks에 쌓인다. 일반적인 메소드를 실행하는 경우 JVM 스택에 쌓이다가 해당 메소드 내부에 네이티브 방식을 사용하는 메소드(예를 들면 C언어로 작성된 메소드)가 있다면 해당 메소드는 네이티브 스택에 쌓인다. 일반 프로그램처럼 커널이 스택을 잡아 독자적으로 프로그램을 실행시키는 영역이다. 이 부분을 통해 C code를 실행시켜 Kernel에 접근할 수 있다.
- Heap
Heap은 객체들이 적재되는 공간, 메소드 지역에서 참조한 값을 바탕으로 새로운 객체를 생성하면 이곳에 적재된다. 물론 classs area영역에 올라온 클래스들만 객체로 생성할 수 있다. 힙은 세부분으로 나눌 수 있다.

- Method Area(= Class Area = Static Area)
인스턴스 생성을 위한 필요 정보(필드, 메소드, 생성자...)를 적재한 공간, 이 공간에는 Runtime Constant Pool이라는 별도의 관리 영역이 함께 존재한다. 이는 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다. Constant Pool에는 해당 Type의 메소드, 필드, 문자열 상수등의 레퍼런스를 가지고 있다. 실제 물리적 메모리 위치를 참조할 때 사용한다. 그리고 종종 바이트 코드를 메모리에 전부 올리기엔 크기 때문에 바이트 코드를 참조할 레퍼런스만 Constant Pool에 저장하고 추후에 해당 값을 참조해서 실행할 바이트 코드를 찾아 메모리에 적재하게 하는 경우도 있다. 또한, Constant Pool을 사용함으로 동적 로딩(dynamic loading)이 가능하다.
* 올라가는 정보의 종류
1) Field Information : 멤버 변수의 이름, 데이터 타입, 접근 제어자에 대한 정보
2) Method Information : 메소드의 이름, 리턴 타입, 매개변수, 접근제어자에 대한 정보
3) Type Information : class인지 interface인지의 여부 저장 /Type의 속성, 전체 이름, super class의 전체 이름(interface 이거나 object인 경우 제외)
Method Area는 클래스 데이터를 위한 공간이라면 Heap영역이 객체를 위한 공간이다.
Heap과 마찬가지로 GC의 관리 대상에 포함된다.
Reference : https://asfirstalways.tistory.com/158
'Back-end' 카테고리의 다른 글
| [Spring] Lombok이란? (0) | 2021.11.15 |
|---|---|
| [Spring Data JPA] JPA(Java Persistence API)란? (0) | 2021.11.15 |
| [Java] Java Pattern 클래스(자바 정규 표현식) - 사용법 (0) | 2021.11.10 |
| [Java] Arrays 클래스에 대해, Arrays 클래스 Method 정리 (0) | 2021.11.09 |
| [Java] 자바에서의 print, printf, println 차이점 (0) | 2021.11.08 |