JVM이란?
JVM 메모리 구조를 설명하기 전에 JVM이 무엇인지 알아야 합니다.
JVM은 Java Virtual Machine의 약자로, 자바 가상 머신이라 부릅니다. 그리고 자바와 운영체제 사이에서 중개자 역할을 수행하며, 자바가 운영체제에 구애 받지 않고 프로그램을 실행할 수 있도록 도와줍니다. 또한, 가비지 컬렉터를 사용한 메모리 관리도 자동으로 수행하며, 다른 하드웨어와 다르게 레지스터 기반이 아닌 스택 기반으로 동작합니다.
<정리>
JVM
- Java Virtual Machine (자바 가상 머신)
- 자바 애플리케이션을 클래스 로더를 통해 읽어 자바 API와 함께 실행
- Garbage Collector(가비지 컬렉터)에 의해 메모리 관리를 자동으로 수행
- 스택 기반의 가상머신
JAVA 프로그램 실행 단계
먼저, 자바 컴파일러에 의해 자바 소스 파일은 바이트 코드로 변환됩니다. 그리고 이러한 바이트 코드를 JVM에서 읽어들인 다음에, 이것저것 복잡한 과정을 거쳐서 어떤 운영체제든 간에 프로그램을 실행할 수 있도록 만드는 것입니다.
JAVA 프로그램 실행 단계 2
JVM의 구조는 크게 보면, Garbage Collector, Execution Engine, Class Loader, Runtime Data Area 4가지로 나눌 수 있습니다.
위에서 설명하였듯이, 자바 소스 파일은 자바 컴파일러에 의해서 바이트 코드 형태인 클래스 파일이 됩니다. 그리고 이 클래스 파일은 클래스 로더가 읽어들이면서 JVM이 수행됩니다.
- Class Loader (클래스 로더)
JVM 내로 클래스를 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈.
런타임 시에 동적으로 클래스를 로드합니다.
- Execution Engine (실행 엔진)
Runtime Data Area에 배치된 바이트 코드들을 명령어 단위로 읽어서 실행시키는 역할
- 인터프리터 : 바이트 코드를 한 줄 씩 실행
- JIT 컴파일러 : 인터프리터 효율을 높이기 위한 컴파일러로 인터프리터가 반복되는 코드를 발견하면 JIT 컴파일러가 반복되는 코드를 네이티브 코드로 바꿔줍니다. 그 다음부터 인터프리터는 네이티브 코드로 컴파일된 코드를 바로 사용합니다.
=> JIT는 바이트 코드를 어셈블러 같은 네이티브 코드로 바꿈으로써 실행이 빠르지만 역시 변환하는데 비용이 발생하기 때문에, JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고, 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일러 방식으로 실행합니다.
- GC (Garbage Collector)
가비지 컬렉터로 힙 영역에서 사용되지 않는 객체들을 탐색 후 제거하는 역할을 합니다.
이 때, GC가 역할을 하는 시간은 언제인지 정확히 알 수 없습니다.
- Runtime Data Area
프로그램 실행 중 사용되는 다양한 영역,, JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역입니다.
Method Area, Heap Area, Stack Area, PC Register, Native Method Stack 으로 나눌 수 있습니다.
- Method area
모든 쓰레드가 공유하는 메모리 영역입니다.
메소드 영역은 클래스, 인터페이스, 메소드, 필드, Static 변수 등의 바이트 코드를 보관합니다.
- Heap area
모든 쓰레드가 공유하며, new 키워드로 생성(동적으로 생성) 된 객체와 배열이 생성되는 영역입니다.
또한, Method area에 로드된 클래스만 생성이 가능하고
Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역입니다.
- Stack area
지역 변수, 파라미터 등이 생성되는 영역.
실제 객체는 Heap에 할당되고 해당 래퍼런스만 Stack에 저장됩니다.
- PC Register
쓰레드가 시작될 때 생성되며, 생성될 때마다 생성되는 공간으로 쓰레드마다 하나씩 존재합니다.
쓰레드가 어떤 부분을 무슨 명령으로 실행해야 할 지에 대한 기록하는 부분으로 현재 수행중인 JVM 명령의 주소를 갖습니다.
- Native method stack
자방 외 언어로 작성된 네이티브 코드를 위한 메모리 영역입니다.
GC가 필요한 이유
- GC는 힙 영역에서 사용하지 않는 객체들을 제거하는 작업을 총칭합니다.
이 객체를 제거하는 작업이 필요한 이유는 자바는 개발자가 메모리를 직접 해제해줄 수 없는 언어이기 때문입니다. 따라서 객체를 사용하고 제거하는 기능이 필요하게 됩니다.
<정리>
Java의 실행방식
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어 자바 바이트코드(.class)로 변환시킵니다.
- Class Loader를 통해 class 파일들을 JVM으로 로딩합니다.
- 로딩된 class 파일들은 Execution engine을 통해 해석됩니다.
- 해석된 바이트코드는 Runtime Data Area 에 배치되어 실질적인 수행이 이루어집니다.