Java 소스코드를 작성 하여 실행시키는 순간 부터, 특정 객체 또는 변수가 GC에 의해 제거되어 생을 마감(?) 하기 까지, 메모리에서 발생되는 과정들을 간략하게 정리해보는 포스트 이다.
(1) Java 소스 코드를 작성 후 실행을 시키면, Java 컴파일러가 실행되면서 Compile 이 진행된다.
Compile이란 프로그래밍 언어로 작성된 소스코드를 기계가 해석할 수 있는 기계어로 변환하는 과정이다.
Compile이 진행 되면, .java 파일 확장자가 .class 확장자로 바뀌며 바이트 코드 파일로 변환된다.
(2) JVM은 소스코드 프로그램 실행을 위해 OS로 부터 메모리(자원)을 할당 받는다.
실행을 위해서 할당 받는 메모리의 영역이 바로 Runtime Data Area 이다.
(3) Class Loader가 compile된 바이트코드 파일을 건네받아서 Runtime Data Area 메모리 영역에 올린다.
흔히 말하는, "소스코드 파일이 메모리에 로드(Loading)된다" 는 말이 지금의 순간을 말하는 것이다.
* Load = 적재하다, 짐을 싣다.
compile 된 .class 확장자 파일은 Runtime Data Area 메모리 영역 중에서 Method Area(아래 사진)에 로드 된다.
(4) 로딩이 완료되면, Execution Engine이 바이트 코드를 실행시킨다.
이때 Execution Engine 은 2가지 방식으로 바이트 코드를 실행시키는데, 다음과 같다.
- 인터프리터를 통해서 코드를 한 줄 씩 번역하고 실행시킨다.
- JIT Compiler(Just-In-Time Compiler)를 통해서 바이트 코드 전체를 번역하고 실행시킨다.
* Execution Engine 은 기본적으로 1번의 방법을 통해 바이트 코드를 실행시키며,
만약 특정 바이트 코드가 중복적으로 자주 실행되면, 해당 바이트 코드를 JIT Compiler를 통해 실행시킨다.
public class test {
public static void main(String[] args) {
Car car = new Car();
}
}
(5) 소스코드가 실행되면, main 메서드가 Stack 영역에 올라간다.
(6) 참조변수 car 의 공간이 Stack 영역에 마련된다.
(7) new 연산자가 실행되어 Car 객체가 Heap 영역에 생성된다. 그리고 Car 객체의 주소값이 참조변수 car 에 할당된다.
* 객체의 생성은 정확히는 Heap 영역 중에서도 Eden 영역에 객체가 할당된다.(아래 사진 참고)
* Car 인스턴스의 인스턴스변수 또한 Car 객체가 Heap 영역에 생성될 때 함께 생성된다.
따라서 인스턴스 변수는 Heap 영역에 생성되는 것이다.
* 지역 변수는 Stack 영역에 생성된다.
(8) 생성자 Car() 가 호출되어 Car 인스턴스의 인스턴스 변수 초기화가 진행된다.
public class test {
public static void main(String[] args) {
Car car = new Car();
car = null; // "" 해당 코드 추가됨 ""
}
}
(9) 참조변수 car 에 null 이 할당되어, 기존에 car 이 가리키던 Car 객체와 참조변수 car 의 연결이 끊어진다.
프로그램이 실행 중 일 때, 이처럼 어떠한 참조변수도 특정 인스턴스를 참조하고 있지 않다면, 해당 인스턴스는 더이상 메모리에 존재할 이유가 없다.
* 이렇게 참조되어 있지 않은 인스턴스를 가비지(Garbage) 라고 한다. ( Also known as Unreachable Object )
* 가비지 컬렉터는 이렇게 참조되고 있지 않은 객체 또는 변수를 검색하여 메모리에서 점유를 해제하며, 메모리 공간을 확보한다.
* 가비지 컬렉터가 메모리 공간을 확보하는 과정을 아래에 이어서 작성하였다.
(10) 7번 과정의 * 에서 작성했던 것 처럼, new 연산자에의해 새롭게 생성되는 객체는 Eden 영역에 생성된다.
만약 Eden 영역이 꽉 차게 된다면 이때 Minor GC가 일어난다. Eden 영역의 Reachable Object 들은 survival 0 영역으로 옮겨지며, Unreachable Object 는 그대로 Eden 영역에 남긴다.
(11) survival 0 영역이 가득차면 survival 0 영역의 Reachable Object 들을 survival 1 영역으로 옮겨준다. 이때, Object 의 age 라는 값을 증가시킨 후 옮겨진다. ( * age 는 이후의 과정인, Old 영역으로 넘어가는 객체를 판단하는 기준이 된다. )
이후, GC에 의해 Eden, survival 0 영역의 Unreachable Object 들이 제거 된다.
(12) survival 1 영역이 가득차면 survival 1 영역의 Reachable Object 들을 이번엔 반대로 survival 0 영역으로 옮겨준다. 이때도 마찬가지로 age 값을 증가시킨 후 옮겨진다. 그리고 survival 1 영역의 Unreachable Object 들은 제거 된다.
(13) survival 영역에 있는 Reachable Object 들의 age 가 일정 수준을 넘게 되면, 해당 객체들은 앞으로 계속 사용될 수 있는 객체라고 판단되어, Old 영역으로 옮겨진다. ( * 해당 과정을 Promotion 이라고 한다.)
(14) 위의 과정이 반복적으로 진행되며, 시간이 흘러 Old 영역도 꽉 차게 된다면 이때 Major GC가 일어난다. Major GC 는 Old 영역의 Unreachable Object 을 제거한다.
Heap 영역
- Young 영역 : 새롭게 생성된 객체가 할당되는 곳이며, 이곳에서는 수많은 객체가 생성되었다가 사라지는 것이 반복된다. 해당 영역에서 활동하는 가비지 컬렉터가 Minor GC 이다.
- Old 영역 : Young 영역에서 참조 상태를 유지하고 살아남은 객체들이 옮겨지는 곳이며, 일반적으로 Young 영역보다 크게 할당 된다. 이 영역에서 활동하는 가비지 컬렉터가 Major GC 이다.
--- 작성중...