자바 메모리 구조

한라봉봉·2023년 12월 16일

JAVA

목록 보기
8/16

1. 자바 메모리 구조

자바 메모리 구조는 크게 메서드 영역, 스택 영역, 힙 영역 3개로 나눌 수 있다.

  1. 메서드 영역(Method Area) : 프로그램을 실행하는데 필요한 공통 데이터를 관리. 이 영역은 프로그램의 모든 영역에서 공유한다.
    1) 클래스 정보: 클래스의 실행코드(바이트 코드), 필드, 메서드와 생성자 코드 등 모든 실행 코드가 존재
    2) static 영역: static 변수들을 보관한다.
    3) 런타임 상수 풀: 프로그램을 실행하는데 필요한 공통 리터럴 상수를 보관한다. 예를 들어서 프로그램에 "hello"라는 리터럴 문자가 있으면 JAVA는 이런 문자를 공통으로 묶어서 관리한다. 프로그램을 효율적으로 관리하기 위한 상수들을 관리한다.

  2. 스택 영역 : 실제 프로그램이 실행되는 영역이다. 자바 실행시, 하나의 실행 스택이 생성된다. 각 스택 프레임은 지역변수, 중간 연산 결과, 메서드 호출 정보 등을 포함한다. 기본형 타입은 스택영역에 값을 직접 저장한다.
    1) 스택 프레임: 스택영역에 쌓이는 네모 박스가 하나의 스택 프레임이다. 메서드를 호출할 때 마다 하나의 스택 프레임이 쌓이고, 메서드가 종료되면 해당 스택 프레임이 제거된다.
    2) 정확히 말하면 스택영역은 각 쓰레드 별로 하나의 실행 스택이 생성된다. 따라서 쓰레드 수 만큼 스택영역이 생성된다.

  3. 힙 영역 : 객체(인스턴스)와 배열이 생성되는 영역이다. new 명령어를 사용하면 이 영역을 사용한다. GC가 이루어지는 주요영역이다.

2. 스택과 큐 자료구조

스택: (LIFO, Last In First Out) 후입선출
큐: (FIFO, First In First Out) 선입선출

3. 메서드 코드는 메서드 영역에 있다

인스턴스의 메서드를 호출하면 실제로는 힙 메모리에 할당하지 않고 메서드 영역에 있는 코드를 불러서 수행한다.
자바에서 특정클래스로 인스턴스를 n개 생성하면, 힙메모리에 n개 인스턴스가 생긴다. 힙 메모리 내에서 각 인스턴스는 내부에 변수와 메서드를 가진다.

같은 클래스로부터 생성된 객체라도, 인스턴스 내부의 변수값은 서로 다를 수있지만, 메서드는 공통된 코드를 공유한다. 따라서 객체가 생성될 때, 인스턴수 변수에는 힙 메모리가 할당되지만, 메서드에 대한 새로운 힙 메모리 할당은 없다.
메서드는 메서드 영역에서 공통으로 관리되고 실행된다.

4. 스택 영역

프로그램 실행과 메서드 호출에는 스택구조가 적합하다.

  1. 자바 main()이 method1()을 호출하고 method1()은 method2()를 호출하는 구조일때, 실행 결과는 아래와 같다.
    주목해야 할 점은 스택 영역에서 후입선출(LIFO, Last In First Out) 방식으로 인해 마지막으로 실행된 메서드가 가장 먼저 종료되고, method2() 스택프레임이 제거된다. 이후에도 실행 역순으로 종료되고 있다.
public class JavaMemoryMain1 {

    public static void main(String[] args) {
        System.out.println("main start");
        method1(10);
        System.out.println("main end");
    }

    static void method1(int m1) {
        System.out.println("method1 start");
        int cal = m1 * 2;
        method2(cal);
        System.out.println("method1 end");
    }

    static void method2(int m2) {
        System.out.println("method2 start");
        System.out.println("method2 end");
    }
}

참고로, 선입선출(FIFO, First In First Out) 인 자료구조는 큐(Queue) 가 있다.

5. 3~4번 정리

  1. 자바는 스택영역을 사용해서 메서드 호출과 지역변수(매개변수 포함)을 관리
  2. 메서드를 계속 호출하면 스택 프레임이 계속 쌓임(메서드를 호출하면 스택프레임이 하나 생성)
  3. 스택 프레임이 종료되면 지역변수도 함께 제거됨
  4. 스택프레임이 제거되면 프로그램도 종료된다.

6. 스택영역과 힙영역 함께 사용하는 경우

Data 클래스

public class Data {
    private int value;

    public Data(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

Main

public class JavaMemoryMain2 {

    public static void main(String[] args) {
        System.out.println("main start");
        method1();
        System.out.println("main end");
    }

    static void method1() {
        System.out.println("method1 start");
        Data data1 = new Data(10);
        method2(data1);
        System.out.println("method1 end");
    }

    static void method2(Data data2) {
        System.out.println("method2 start");
        System.out.println("data.value=" + data2.getValue());
        System.out.println("method2 end");
    }

}


1. main() 메서드 실행시 main() 스택 프레임이 생성
2. main()에서 method1 실행시 method1() 스택 프레임 생성
1) method1()은 지역 변수로 Data data1을 가지고 있다. method1() 스택 프레임에 포함된다.
3. method1()은 new Data(10)을 사용해서 힙 영역에 Data 클래스의 인스턴스를 생성한다. 참조값은 data1에 보관한다.

  1. method1()은 method2() 호출, Data data2 매개변수에 참조값을 넘긴다.
  2. method1()의 data1과 method2()의 data2 지역변수(매개변수 포함)는 둘다 같은 인스턴스를 참조한다.
  3. method2() 종료, 스택프레임이 제거되면서 매개변수 data2도 함께 제거
  4. method1() 종료, 스택프레임이 제거되면서 지역변수 data1도 함께 제거
    1)이때, Data 인스턴스는 참조하는 곳이 없으므로 GC 대상이된다.
  5. main() 종료
profile
백엔드 개발공부 로그를 기록합니다

0개의 댓글