이 글은 '스프링 입문을 위한 자바 객체 지향의 원리와 이해' 책을 읽고 작성한 글입니다.
자바를 공부하면서 메모리 구조에 대한 개념은 자바를 처음 공부했던 초창기부터 많이 들었었습니다. Method Area, Heap, Stack 등등... 이번 글에서는 실제 예제를 통해 메모리가 어떻게 적재되고 사용되는지 공부하면서 작성한 글입니다.
프로그램이 메모리를 사용하는 공통된 방식은 크게 코드 실행 영역, 데이터 저장 영역으로 분리해서 사용합니다.
객체 지향 프로그램에서는 데이터 저장영역을 다시 3개의 영역으로 분할해 사용합니다. 이와 같은 구조를 T 메모리 구조라 부르고(T처럼 보이기에) 자바는 대표적인 객체 지향 언어이므로 T메모리 구조를 사용합니다.
위와 같은 메모리 구조에서 아래 main()문은 실행했을 때 어떻게 변화하는지 확인해보자
Start.java
public class Start {
public static void main(String[] args) {
System.out.println("Hello OOP!!");
}
}
JVM이 제일 먼저 하는 일은 전처리라고 하는 과정입니다.
이제 모든 전처리 과정은 끝났습니다.
전처리과정에 대해 다시 한번 정리해보겠습니다.
System.out.println("Hello OOP!!");
부분이 실행되지 않았습니다.
메서드들의 놀이터는 스택영역입니다.
main()가 놀기 위해 스택 프레임이 아래와 같이 스택 영역에 할당됩니다.(조금 더 정확히 말하자면 여는 중괄호를 만날 때마다 스택프레임이 생긴다(클래스를 정의하는 여는 중괄호 제외))
이제는 System.out.println("Hello OOP!!") 구문을 실행할까요?
아직도 아닙니다.
메서드의 인자 args를 저장할 변수공간을 스택 프레임의 맨 밑에 확보해야합니다. 즉 메서드 인자의 변수 공간을 할당하는 것 입니다.
아래와 같이 T메모리를 구성하고 나서야 main()메서드 안의 첫 명령문을 실행하게 됩니다.
별거없는 프로그램이었지만 JRE와 JVM은 참 바빴습니다. JRE는 눈에 보이지 않게 뒤에서 JVM이라고 하는 자바 가상 기계를 부팅하고, JVM은 메모리 구조를 만들고 거기에 java.lang 패키지 로딩, 각종 클래스 로딩, main() 메서드 스택 프레임 배치, 변수 공간 배치 등등의 일을 처리했습니다.
Start.java
public class Start {
public static void main(String[] args) {
System.out.println("Hello OOP!!");
}
}
4번째 줄에서 main() 메서드의 끝을 나타내는 닫는 중괄호와 만나게 되고 아래과 같이 스택 프레임이 소멸됩니다.
-> 여는 중괄호로 스택 프레임이 만들어지고 닫는 중괄호로 스택 프레임이 소멸됩니다.
main() 메서드가 프로그램의 시작점이자 끝이기도 합니다.
main() 메서드가 끝나면 JRE는 JVM을 종료하고 JRE 자체도 운영체제 상의 메모리에서 사라집니다. 그럼 T메모리도 이제 운명을 다하고 사라집니다.
실제로 자바프로그램이 실행할 때 메모리가 어떻게 적재되는지 공부해봤습니다. 메모리에 대한 이론적으로는 어느정도 알고있었지만 실제 예제를 통해 어떻게 적재되는지 정확히 이해하기 되니 앞으로 코드를 짤 때도 조금 더 메모리를 신경쓰면서 개발하도록 해야겠다.
제가 잘못이해하고 있거나 잘못 작성한 부분이 있다면 지적, 비판, 피드백 뭐든 해주시면 감사하겠습니다!