[Java] main() 메서드가 실행될 때, T메모리에서는 무슨 일이 일어날까?

모지리 개발자·2022년 9월 16일
2
post-thumbnail

이 글은 '스프링 입문을 위한 자바 객체 지향의 원리와 이해' 책을 읽고 작성한 글입니다.

Intro

자바를 공부하면서 메모리 구조에 대한 개념은 자바를 처음 공부했던 초창기부터 많이 들었었습니다. Method Area, Heap, Stack 등등... 이번 글에서는 실제 예제를 통해 메모리가 어떻게 적재되고 사용되는지 공부하면서 작성한 글입니다.

T 메모리란?

프로그램의 공통된 메모리 사용방식


프로그램이 메모리를 사용하는 공통된 방식은 크게 코드 실행 영역, 데이터 저장 영역으로 분리해서 사용합니다.

객체지향 프로그램의 메모리 사용방식


객체 지향 프로그램에서는 데이터 저장영역을 다시 3개의 영역으로 분할해 사용합니다. 이와 같은 구조를 T 메모리 구조라 부르고(T처럼 보이기에) 자바는 대표적인 객체 지향 언어이므로 T메모리 구조를 사용합니다.

스태틱(static) 영역

  • JVM이 실행되면서 생기는 공간
  • Class정보, 전역변수 정보, Static 변수 정보가 저장되는 공간
  • class영역 혹은 method영역이라고도 볼림
  • 모든 쓰레드에 정보 공유

스택(stack) 영역

  • 지역변수, 메소드의 매개변수와 같이 잠시 사용되고 필요가 없어지는 데이터가 저장되는 공간
  • LIFO(Last In First Out)
  • 지역변수이지만 Reference Type의 경우 Heap에 저장된 데이터의 주소값을 Stack에 저장해서 사용
  • 쓰레드 마다 하나씩 존재(공유X)

힙(heap) 영역

  • new 연산자로 생성된 객체, Array와 같은 동적으로 생성된 데이터가 저장되는 공간
  • GC의 대상이 되는 영역
  • 모든 쓰레드에 정보 공유

Main() 메서드를 실행해보자

위와 같은 메모리 구조에서 아래 main()문은 실행했을 때 어떻게 변화하는지 확인해보자

Start.java

public class Start {
    public static void main(String[] args) {
        System.out.println("Hello OOP!!");
    }
}
  1. JRE는 Start 클래스에서 main() 메서드를 발견합니다.
  2. main() 메서드의 존재가 확인되면 JRE는 프로그램 실행을 위한 사전 준비에 착수합니다.(가상 기계인 JVM에 전원을 넣어 부팅)

JVM이 제일 먼저 하는 일은 전처리라고 하는 과정입니다.

  1. JVM은 java.lang 패키지를 T메모리의 스태틱 영역에 가져다 놓습니다.(java.lang 패키지가 있기에 System.out.println() 과 같은 메서드를 쓸 수 있게됩니다.)
  1. JVM은 개발자가 작성한 모든 클래스와 임포트 패키지 역시 스태틱 영역에 가져다 놓습니다. 그래서 스태틱 영역을 "클래스들의 놀이터"라고 합니다.
    현재 코드에서는 클래스는 Start 뿐이니 T메모리에는 아래와 같이 배치됩니다.

이제 모든 전처리 과정은 끝났습니다.

전처리과정에 대해 다시 한번 정리해보겠습니다.

  • java.lang 패키지를 T메모리의 스태틱 영역에 배치한다.
  • import 된 패키지를 T메모리의 스태틱 영역에 배치한다.
  • 프로그램 상의 모든 클래스를 T메모리 스태틱 영역에 배치한다.

아직은

System.out.println("Hello OOP!!");

부분이 실행되지 않았습니다.

메서드들의 놀이터는 스택영역입니다.
main()가 놀기 위해 스택 프레임이 아래와 같이 스택 영역에 할당됩니다.(조금 더 정확히 말하자면 여는 중괄호를 만날 때마다 스택프레임이 생긴다(클래스를 정의하는 여는 중괄호 제외))

이제는 System.out.println("Hello OOP!!") 구문을 실행할까요?
아직도 아닙니다.
메서드의 인자 args를 저장할 변수공간을 스택 프레임의 맨 밑에 확보해야합니다. 즉 메서드 인자의 변수 공간을 할당하는 것 입니다.
아래와 같이 T메모리를 구성하고 나서야 main()메서드 안의 첫 명령문을 실행하게 됩니다.

별거없는 프로그램이었지만 JRE와 JVM은 참 바빴습니다. JRE는 눈에 보이지 않게 뒤에서 JVM이라고 하는 자바 가상 기계를 부팅하고, JVM은 메모리 구조를 만들고 거기에 java.lang 패키지 로딩, 각종 클래스 로딩, main() 메서드 스택 프레임 배치, 변수 공간 배치 등등의 일을 처리했습니다.

실행이 끝났는데 T 메모리는 이제 어떻게 될까?

Start.java

public class Start {
    public static void main(String[] args) {
        System.out.println("Hello OOP!!");
    }
}

4번째 줄에서 main() 메서드의 끝을 나타내는 닫는 중괄호와 만나게 되고 아래과 같이 스택 프레임이 소멸됩니다.
-> 여는 중괄호로 스택 프레임이 만들어지고 닫는 중괄호로 스택 프레임이 소멸됩니다.

main() 메서드가 프로그램의 시작점이자 끝이기도 합니다.
main() 메서드가 끝나면 JRE는 JVM을 종료하고 JRE 자체도 운영체제 상의 메모리에서 사라집니다. 그럼 T메모리도 이제 운명을 다하고 사라집니다.

결론

실제로 자바프로그램이 실행할 때 메모리가 어떻게 적재되는지 공부해봤습니다. 메모리에 대한 이론적으로는 어느정도 알고있었지만 실제 예제를 통해 어떻게 적재되는지 정확히 이해하기 되니 앞으로 코드를 짤 때도 조금 더 메모리를 신경쓰면서 개발하도록 해야겠다.

제가 잘못이해하고 있거나 잘못 작성한 부분이 있다면 지적, 비판, 피드백 뭐든 해주시면 감사하겠습니다!

profile
항상 부족하다 생각하며 발전하겠습니다.

0개의 댓글