처음부터 차근차근

[Java] Java 메모리 구조 본문

Language/Java

[Java] Java 메모리 구조

HangJu_95 2023. 12. 29. 18:01
728x90

Java의 메모리 구조

  • 메서드 영역(Method Area) : 메서드 영역은 프로그램을 실행하는데 필요한 공통 데이터를 관리합니다. 이 영역은 프로그램의 모든 영역에서 공유합니다.
    • 클래스 정보 : 클래스의 실행 코드(Byte Code), Field, Method와 생성자 코드 등 모든 실행코드가 존재합니다.
    • static 영역: Static 변수들을 보관합니다.
    • Runtime 상수 풀 : 프로그램을 실행하는데 필요한 공통 리터럴 상수를 보관합니다. 예를 들어 "hello"라는 리터럴 문자가 있으면 이런 문자를 공통으로 묶어서 관리합니다. 이 외에도 프로그램을 효율적으로 관리하기 위한 상수들을 관리합니다.
  • 스택 영역(Stack Area) : 자바 실행 시, 하나의 실행 스택이 생성됩니다. 각 스택 프레임은 지역 변수, 중간 연산 결과, 메서드 호출 정보 등을 포함합니다.
    • 스택 프레임 : 스택 영역에 쌓이는 네모 박스가 하나의 스택 프레임입니다. 메서드를 호출할 때 마다 하나의 스택 프레임이 쌓이고, 메서드가 종료되면 해당 스택 프레임이 제거됩니다.
  • 힙 영역(Heap Area) : 객체(인스턴스)와 배열이 생성되는 영역입니다. garbage collection이 이루어지는 주요 영역이며, 더 이상 참조되지 않는 객체는 GC에 의해 제거됩니다.
참고 : 스택 영역은 더 정확히는 각 쓰레드 별로 하나의 실행 스택이 생성됩니다. 따라서 쓰레드 수 만큼 스택 영역이 생성됩니다.

메서드 코드는 메서드 영역에

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

스택 영역

다음 코드 예시를 보겠습니다.

package memory;

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");
    }
}

 

실행 결과

호출 그림

  • 처음 자바 프로그램을 실행하면 main()을 실행합니다. 이때 main()을 위한 스택 프레임이 하나 생성됩니다.
    • main() 스택 프레임은 내부에 args라는 매개변수를 가집니다.
  • main()은 System.out.println("main start") 을 지나 method1을 호출합니다. method1() 스택 프레임이 생성됩니다.
    • method1()는 m1, cal 지역 변수(매개변수 포함)를 가지므로 해당 지역 변수들이 스택 프레임에 포함됩니다.
  • method1()도 마찬가지로 sout을 지나 method2()를 호출합니다. method2() 스택 프레임이 생성되고, m2 지역변수를 가지므로 해당 지역 변수가 스택 프레임에 포함됩니다.

종료 그림

  • method2()가 종료됩니다. 이때 method2() 스택 프레임이 제거되고, 매개변수 m2도 제거됩니다. method2() 스택 프레임이 제거 되었으므로 프로그램은 method1()로 돌아갑니다. 물론 method1()을 처음부터 시작하는 것이 아니라 method1() 에서 method2() 를 호출한 지점으로 돌아갑니다.
  • method1() 이 종료됩니다. 이때 method1() 스택 프레임이 제거되고, 지역 변수(매개변수 포함) m1, cal도 제거됩니다. 프로그램은 main() 으로 돌아갑니다.
  • main()이 종료됩니다. 더 이상 호출할 메서드가 없고, 스택 프레임도 완전히 비워지며, 자바는 프로그램을 정리하고 종료합니다.

정리

  • 자바는 스택 영역을 사용해서 메서드 호출과 지역 변수(매개변수 포함)를 관리한다.
  • 메서드를 계속 호출하면 스택 프레임이 계속 쌓인다.
  • 지역 변수(매개변수 포함)는 스택 영역에서 관리한다.
  • 스택 프레임이 종료되면 지역 변수도 함께 제거된다.
  • 스택 프레임이 모두 제거되면 프로그램도 종료된다.

스택 영역과 힙 영역

이번에는 스택 영역과 힙 영역이 함꼐 사용되는 경우를 살펴보겠습니다.

package memory;

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");
    }
}
package memory;

public class Data {
    private int value;

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

    public int getValue() {
        return value;
    }
}

 

  • method1()에서 실행 시 Data 생성자를 이용하여 data1을 생성하였고, 참조값을 data1에 보관하고 있습니다.
  • method1()은 method2()를 호출하면서 Data data2 매개변수에 참조값을 넘깁니다.
  • 이제 method1()에 있는 data1과 method2()에 있는 data2 지역 변수는 둘 다 같은 인스턴스를 참조합니다.

  • method1()이 종료된 직후, data2, data1까지 함께 제거되었으며, x001 참조값을 가진 Data 인스턴스를 참조하는 곳이 없습니다.
  • 따라서 사용되는 곳이 없음으로, GC에서 자동으로 메모리에서 제거합니다.

참고로, 힙 영역 외부가 아닌 힙 영역 안에서만 인스턴스끼리 서로 참조하는 경우에도 GC의 대상이 됩니다.

(Java 자체에서 참조값을 가져올 수가 없기 때문입니다.)

 

메서드 영역은 static 키워드와 같이 한번 정리해보겠습니다.

참조

 

김영한의 실전 자바 - 기본편 강의 - 인프런

실무에 필요한 자바 객체 지향의 핵심 개념을 예제 코드를 통해 쉽게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을 안다

www.inflearn.com

 

'Language > Java' 카테고리의 다른 글

[Java] final  (1) 2023.12.31
[Java] static  (2) 2023.12.29
[Java] 제어자, 접근 제어자  (0) 2023.12.26
[Java] Package  (1) 2023.12.26
[Java] 생성자, this  (1) 2023.12.26