자바로 작성한 소스 코드를 해석해 실행하는 별도의 프로그램
JVM이 자바 프로그램과 운영체제 사이에서 일종의 통역가 역할을 수행한다.
운영체제에 맞게 JVM이 개발되어져 있으며, JVM은 자바 소스 코드를 운영체제에 맞게 변환해 실행시켜준다. 이것이 자바가 운영체제로부터 독립적으로 동작할 수 있는 이유이다.
자바로 소스 코드를 작성하고 실행하면, 먼저 컴파일러가 실행되면서 컴파일이 진행된다. 컴파일의 결과로 .java 확장자를 가졌던 자바 소스코드가 .class 확장자를 가진 바이트 코드 파일로 변환된다.
JVM은 운영체제로부터 소스 코드 실행에 필요한 메모리를 할당받는다. 이것이 위 사진에 런타임 데이터 영역이다.
클래스 로더가 바이트 코드 파일을 JVM 내부로 불러들여 런타임 데이터 영역에 적재시킨다. 즉, 자바 소스 코드를 메모리에 로드시킨다.
로드가 완료되면 실행 엔지이 런타임 데이터 영역에 적재된 바이트 코드를 실행시킨다.
실행 엔진은 기본적으로 인터프리터를 통해 바이트 코드를 실행시키다가, 특정 바이트 코드가 자주 실행되면 해방 바이트 코드를 JIT Compiler를 통해 실행시킨다.
즉, 중복적으로 어떤 바이트 코드가 등장할 때, 인터프리터는 매 번 해당 바이트 코드를 해석하고 실행하지만, JIT 컴파일러가 동작하면 한번에 바이트 코드를 해석하고 실행시킨다.
스택은 일종의 자료구조이다. LIFO : 마지막으로 들어온 데이터가 가장 먼저 나가는 자료구조
메서드가 호출되면 그 메서드를 위한 공간이 Method Frame이 생성된다.
메서드 내부에서 사용하는 다양한 값들이 있는데 참조변수, 매개변수, 지역변수, 리턴값 및 연산시 일어나는 값들이 임시로 저장된다.
이런 Method Frame이 Stack에 호출되는 순서대로 쌓이게 되는데, Method의 동작이 완료되면 역순으로 제거된다.
JVM이 작동되면 이 영역은 자동 생성된다. 그리고 이 영역안에 객체나 인스턴스 변수, 배열이 저장된다.
Person person = new Person();
new Person()이 실행되면 Heap 영역에 인스턴스가 생성되며, 인스턴스가 생성된 위치의 주소 값을 person에게 할당해주는데, 이 person은 Stack 영역에 선언된 변수이다.
즉, 객체를 다룬다는 것은 Stack 영역에 저장되어 있는 참조 변수를 통해 Heap 영역에 존재하는 객체를 다룬다는 의미가 된다.
Heap 영역은 실제 객체의 값이 저장되는 공간이다.
메모리를 자동으로 관리하는 프로세스이다. 프로그램에서 더 이상 사용하지 않는 객체를 찾아 삭제하거나 제거하여 메모리를 확보하는 것을 의미한다.
JVM의 Heap 영역은 객체는 대부분 일회성이ㅕㅁ, 메모리에 남아 있는 기간이 대부분 짧다는 전제로 설계되었다.
그래서 얼마나 살아있냐에 따라서 Heap 영역도 Young, Old 영역으로 나뉜다.
새롭게 생성된 객체가 할당되는 곳이고 많은 객체가 생성되었다가 사라지는 것읇 반복한다.
여기서 활동하는 GC를 Minor GC라고 한다.
Young 영역에서 상태를 유지하고 살아남은 객체들이 복사되는 곳으로 보통 Young 영역보다 크게 할당되고 크기가 큰 만큼 가비지는 적게 발생한다.
여기서 활동하는 GC를 Major GC라고 한다.
이 두 영역은 가비지 컬렉션이 실행 단계는 아래와 같다.
가비지 컬렉션이 실행될때 가비지 컬렉션을 실행하는 스레드를 제외한 모든 스레드들의 작업은 중단되고, 가비지 정리가 완료되면 재개됩니다.