들어가기 전, JVM 이란?
- Java Virtual Machine의 약자로, 자바 프로그램 실행 환경을 만들어주는 소프트웨어이다.
- JVM에는 자바 실행 환경(Jave Runtime Environment)가 포함되어 있고, 컴퓨터 OS에 맞는 JRE가 설치되어 있으면 JVM이 설치되어 있다는 뜻임
JVM의 동작 방식
- 자바 프로그램을 실행하면 JVM이 OS로부터 메모리를 할당한다.
- 자바 컴파일러(javac)가 .java 소스 코드를 바이트코드(.class)로 컴파일한다.
- Class Loader를 통해 JVM Runtime Data Area를 로딩한다.
- RDA에 로딩 된 바이트 코드(.class)들은 실행 엔진(Execution Engine)을 통해 해석한다.
- 해석된 바이트 코드는 RDA의 각 영역에 배치되어 수행하며 이 과정에서 EE에 의해 CG 동작과 쓰레드 동기화가 이루어진다.
Java와 JVM의 특징
- Java는 플랫폼에 독립적이고, JVM은 플랫폼에 종속적이다.
- Java는 자바 컴파일러에 의해 컴파일 되면 바이트 코드가 생성되고, 해당 바이트 코드를 플랫폼에 맞게 JVM이 변환해준다.
- 따라서, 바이트 코드는 어떤 JVM에서도 동작할 수 있기 때문에 플랫폼에 독립적이고, JVM은 플랫폼에 맞는 JVM이 각각 따로 있기 때문에 플랫폼에 종속적인 것이다.
JVM의 구조
-
클래스 로더(Class Loader)
-> 런타임 시 동적으로 클래스를 로딩해주는 역할
-> .java 소스를 컴파일하여 생성된 바이트 코드(.class)를 JVM이 RDA(Runtime Data Area)로 배치시킨다.
-
실행 엔진(Execution Engine)
-> 배치된 바이트 코드들을 명령어 단위로 읽어서 실행하는 런타임 모듈이 실행 엔진이다.
-> 바이트 코드를 읽는 방식에는 Interpreter 방식과 JIT 컴파일 방식 두 가지가 있다. 두 방식에 대한 내용은 링크에서 설명
-
가비지 컬렉터(Garbage Collector)
-> 사용(참조)되지 않는 메모리(객체)를 탐색하여 자동으로 회수해주는 역할
-> GC가 역할을 하는 시간은 정확히 알 수 없다.
-> GC가 역할을 수행하는 동안 GC의 쓰레드 외에 나머지 쓰레드들은 일시정지 상태가 된다.
-> GC에 대한 상세 내용은 링크 참조.
-
런타임 데이터 영역(Runtime Data Area)
-> JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.
- 모든 쓰레드가 공유해서 사용(GC의 대상이 됨)
- 메소드 영역(Method(=Static) Area)
- 힙 영역(Heap Area)
- 쓰레드마다 하나씩 생성
- 스택 영역(Stack Area)
- PC Register
- Native Method Stack
런타임 데이터 영역(Runtime Data Area)
1. 메소드 영역(Method/Static Area)
- 클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 각종 필드 정보들과 메소드 정보, 데이터 Type 정보, Constant Pool, static 변수, final class 등이 생성되는 영역
- file data(필드 데이터) : 멤버 변수이름, 타입, 접근제어자등의 메타정보
- method data(메서드 데이터) : 메서드 이름, 리턴타입, 매개변수, 접근제어자등의 메타정보
- constructor(생성자) : 생성자 메서드에 관한 정보.
- static 변수(Class 변수) : 모든 객체가 공유할 수 있는 정적 클래스 변수.
- runtime constant pool (런타임 상수 풀)
- Method(Static) 영역에 있는 것은 어느 곳에서나 접근 가능
- Method(Static) 영역의 데이터는 프로그램의 시작부터 종료가 될 때까지 메모리에 남아있다.
그래서 static 메모리에 있는 데이터들은 프로그램이 종료될 때까지 어디서든 사용이 가능하다.
그러나 static 데이터를 무분별하게 많이 사용할 경우 메모리 부족 현상이 일어날수 있게 된다.
🔍 Runtime Constant Pool
- 메소드 영역(Method(Static) Area)에 존재하는 별도의 관리 영역
- 각 클래스/인터페이스마다 별도의 Constant Pool 테이블이 존재하는데, 클래스를 생성할 때 참조해야 할 정보들을 상수로 가지고 있는 영역임
- JVM은 Constant Pool을 통해 해당 메소드나 필드의 실제 메모리 상 주소를 찾아 참조함
- 상수 자료형을 저장하여 참조하고 중복을 막는 역할
- 상수 풀은 Method Area, 즉 정적 영역에 있는 메모리이기에 GC의 대상이 아님
- Primarity Type 뿐만 아니라 String 객체, 레퍼런스 타입이 가진 주소 값도 상수 풀로 관리됨
2. 힙 영역(Heap Area)
- Heap 영역은 위와 같이 3가지 영역으로 나뉨
- Young Generation 영역은 생성된지 얼마되지 않은 객체가 저장되는 공간
- 객체가 생성되면 Eden 영역에 할당됨 -> Eden 영역에 일정 데이터가 쌓이게 되면 참조 정도에 따라 Survivor의 빈 공간으로 이동 또는 회수 됨
- Tenured Generation 영역은 Young Generation 영역이 다 차게 되면 참조 정도에 따라 해당 영역으로 이동 또는 회수 됨
- Heap 영역의 동작은 GC와 연관되며, 상세 내용은 위의 GC 관련 링크에서 확인
- 위 내용의 중점은 Heap 영역에서는 메모리 호출이 끝나더라도 남아있게 되고, 더 이상 사용하지 않게되면 GC에 의해 메모리에서 회수된다는 것
- new 키워드로 생성된 객체와 배열(Reference Type)이 생성되는 영역, 런타임 시 동적으로 할당되어 사용되는 영역
- Heap 영역에 있는 객체를 가리키는 레퍼런스 변수는 Stack에 적재 됨
- Heap 영역은 스레드와 상관없이 단 하나의 영역만 존재
3. 스택 영역(Stack Area)
- 지역변수, 파라미터(매개변수), 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역
- Primitive Type의 데이터에 해당되는 지역변수, 매개 변수 등이 저장 됨
- 메소드가 호출될 때 스택 영역에 Stack Frame이 생성된 후 메소드를 호출 함
- Stack Frame이란, 하나의 메소드에 필요한 메모리 덩어리를 말함
- 하나의 메소드 당 하나의 Stack Frame이 필요함
- 스택 메모리에 쌓이는 데이터가 위에서 언급한 지역변수, 파라미터, 리턴 값 등이 있다.
- 메모리 호출 및 할당 후 종료되면 메모리에서 제거 됨
- 후입선출(Last-In-First-Out)의 특성을 가지며, 호출 범위를 벗어나면 스택에서 제거 됨
4. PC Register 영역
- 쓰레드가 생성될 때 마다 생성되는 영역으로, 쓰레드마다 하나씩 존재함
- 현재 쓰레드가 실행되는 부분의 JVM 주소와 명령을 저장하고 있음
5. Native Method Stack 영역
- 자바 이외의 언어(C, C++, 어셈블리 등)로 작성된 네이티브 코드를 실행할 때 사용되는 메모리 영역
참고 Reference