JVM이란?
JVM은 Java Virtual Machine의 약자로 자바 가상 머신이다.
자바는 컴파일 단계에서 자바 바이트코드로 변환되는데 JVM은 변환된 자바 바이트코드를 해석하고 실행하는 역할을 한다.
자바 바이트코드
- JVM은 사용자 언어인 자바와 기계어 사이의 중간 언어인 바이트코드를 사용한다.
- 자바 코드를 배포하는 가장 작은 단위이다.
- 자바 컴파일러는 C/C++ 처럼 고수준 언어를 직접적인 CPU 명령어로 변환하는 것이 아니라, 개발자가 이해하는 자바 언어를 JVM이 이해하는 자바 바이트코드로 변역한다.
- 따라서 JVM이 설치된 장비라면 CPU나 운영체제가 다르더라고 실행 가능하다.
JVM 구조
자바로 작성된 코드의 실행과정을 보면 구조를 알 수 있다.
- 컴파일 단계에서 자바 코드(.java)가 자바 바이트코드(.class)로 변환된다.
- 클래스 로더에 의해 Runtime Data Areas에 변환된 자바 바이트코드를 적재한다.
- 실행 엔진이 적재된 자바 바이트코드를 실행한다.
이렇게 자바의 실행 구조를 확인할 수 있었다.
클래스 로더와 자바 바이트코드에 대해 좀 더 자세히 알고싶다면 참고자료의 링크된 블로그를 참고하길 바란다.
사실 가장 알고싶은 부분은 JVM의 전체 구조가 아닌 어플리케이션이 실행되면서 메모리가 할당되는 Runtime Data Areas부분이다.
런타임 데이터 영역은 6개의 영역으로 구분할 수 있으며 쓰레드간의 공유 여부를 통해 한 번 더 구분할 수 있다.
매 쓰레드마다 생성
- PC Register
- 스레드가 시작될 때 생성되며, PC 레지스터는 현재 수행 중인 JVM 명령의 주소를 갖는다.
- JVM Stack
- 스택 프레임이라는 구조체를 저장하는 스택으로 해당 구조체를 push 및 pop하는 역할을 한다. 흔히 예외가 발생했을 때 prinStackTrace()는 스택의 스택 프레임들을 표현한다.
- 스택 프레임은 JVM 내에서 메서드가 수행될 때 마다 하나씩 생성된다.
- 각 스택 프레임은 지역 변수 배열, 피연산자 스택, 현재 실행 중인 메서드가 속한 클래스의 런타임 상수 풀에 대한 참조를 갖는다.
- Native Method Stack
- C나 C++ 등 자바 외의 언어로 작성된 네이티브 코드를 위한 스택이다.
- 언어에 맞는 스택이 생성된다.
쓰레드간의 공유
- Heap
- 생성된 객체 혹은 인스턴스를 저장하는 공간이며 가비지 컬렉션 대상이다.
- 어떠한 메서드에서 인스턴스가 생성되었다면 해당 인스턴스는 이곳에 저장되고 인스턴스를 참조하는 변수는 해당 메서드의 스택 프레임 내의 존재한다.
- Method Area
- JVM이 읽어 들인 각각의 클래스와 인터페이스에 대한 런타임 상수 풀, 필드와 메서드 정보, Static 변수, 메서드의 바이트코드 등을 보관한다.
- Runtime Constant Pool
- 클래스 파일 포맷에서 constant_pool 테이블에 해당하는 영역이다.
- 메서드 영역에 포함되는 영역이긴 하지만, JVM 동작에서 가장 핵심적인 역할을 수행하는 곳이기 때문에 JVM 명세에서도 따로 중요하게 기술한다.
- 각 클래스와 인터페이스의 상수뿐만 아니라, 메서드와 필드에 대한 모든 레퍼런스까지 담고 있는 테이블이다. 즉, 어떤 메서드나 필드를 참조할 때 JVM은 런타임 상수 풀을 통해 해당 메서드나 필드의 실제 메모리상 주소를 찾아서 참조한다.
마치며 참조된 링크를 통해 바이트코드, 클래스 로더, 실행 엔진 등 좀 더 자세히 정리가 되어있다.
이번 게시글은 JVM의 기본 구조 및 흐름을 이해해가 위한 정리이며 추후 각 파트의 자세한 조사를 통해 보충할 예정이다.
---
'개발 > Java' 카테고리의 다른 글
Iterator는 무엇이고 왜 사용하는가 (0) | 2022.03.01 |
---|