< JVM(Java Virtual Machine) >
- JVM 역할은 자바 애플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행하는 것
- 또한, Java와 OS 간의 중개자 역할을 수행하여 OS에 구애받지 않고 재사용을 가능하게 한다.
- 메모리관리 및 Garbage Collection 역할을 수행하며 Stack 기반의 가상머신이다.
< Java 프로그램 실행 과정 >
- 프로그램이 실행되면 JVM은 OS로부터 이 프로그램이 필요로 하는 메모리를 할당받는다.
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어들여 자바 바이트코드(.class)로 변환시킨다.
- Class Loader를 통해 class파일들을 JVM으로 로딩한다.
- 로딩된 class파일들은 Execution engine을 통해 해석된다.
- 해석된 바이트코드는 Runtime Data Areas 에 배치되어 실질적인 수행이 이루어지게 된다.
Class Loader(클래스 로더)
- 클래스 로더는 .class 파일을 읽어 바이트 코드를 메소드 영역(Method Area)에 저장한다.
- Runtime 시에 클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링크하는 역할을 수행한다.
< Runtime Data Area >
- 프로그램 수행을 위해 os로부터 할당받는 메모리 영역으로 5가지로 볼 수 있다.
Method area
- 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리공간이다.
- 클래스 이름, 부모 클래스 이름, 메소드, 변수 정보 등과 같은 수준의 모든 클래스 정보와 static 변수들을 저장한다.
Heap area
- 모든 객체를 저장하는 가상 메모리 공간이다. new 연산자로 생성된 객체와 배열을 저장한다.
Stack area
- 프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역이다.
- 각종 형태의 변수나 임시 데이터, 스레드, 메소드 정보를 저장한다.
PC Registers
- Thread가 어떤 부분을 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행중인 JVM 명령의 주소를 가진다.
Native Method Stacks
- 자바 프로그램이 컴파일되어 생성되는 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역이다.
< Execution Engine(실행 엔진) >
- 바이트 코드로 된 .class 파일을 실행한다. 바이트 코드를 한줄씩 읽고 다양한 메모리 영역에 나타난 데이터와 정보를 사용한다.
Interpreter
- 실행 엔진은 바이트코드를 한줄씩 읽어서 실행한다. 단점은 여러번 하나의 메소드를 호출할 경우 매번 해석을 요청해야하기 때문에 비효율적이다.
JIT(Just-In-Time)
- 인터프리터 방식의 단점을 보완하기 위해 도입된 JIT 컴파일러이다.
- 전체 바이트 코드를 컴파일하고 네이티브 코드로 변경하여 더이상 인터프리팅 하지 않고 네이티브 코드로 직접 실행하는 방식이다.
- JIT 컴파일러를 사용하는 JVM은 내부적으로 해당 메서드가 자주 수행되는지 체크하고, 일정 정도를 넘을 때 네이티브 코드로 변경한다.
< Garbage Collector >
- 메모리 관리를 위한 방법 중의 하나로, Heap 영역 안의 Garbage를 찾아내서 Heap의 메모리를 회수한다.
- 참조되고 있지 않은 객체를 Garbage라고 하며, Garbage를 판별하기 위해 Reachability 개념을 사용한다.
- 한 객체가 다른 객체를 참조하며 다른 객체는 또다른 객체를 참조할 경우에는 유효한 최초의 참조가 무엇인지 파악해야 되는데, 이를 객체 참조의 root set이라고 한다.
- 힙 내의 다른 객체에 의한 참조
- Java 스택, 즉 Java 메서드 실행 시에 사용하는 지역 변수와 파라미터들에 의한 참조
- 네이티브 스택, 즉 JNI(Java Native Interface)에 의해 생성된 객체에 대한 참조
- 메서드 영역의 정적 변수에 의한 참조
- 2, 3, 4번의 참조의 경우 root set이 되어 reachability를 판가름하는 기준이 된다.
- 즉 root set으로부터 시작한 객체들은 reachable이며, root set과 무관한 객체들이 unreachable 객체로 GC의 대상이 된다.
메모리 누수 현상
- 컴퓨터 프로그램이 필요하지 않은 메모리를 계속 점유하고 있는 현상이다.
- 메모리 동적 할당시 Heap 영역에 할당되는데, 사용자가 해제하지 않는 경우 Heap 영역 메모리 공간을 계속 차지하게 된다.
- 이는 메모리 부족으로 시스템이 다운될 수도 있는 위험이 있다.
- Java에서 Garbage Collector가 없다면 메모리 누수의 위험이 높다.