Skip to content

Latest commit

 

History

History
115 lines (75 loc) · 8.37 KB

File metadata and controls

115 lines (75 loc) · 8.37 KB

자바 메모리 구조

Image

자바의 메모리 구조는 크게 메서드 영역, 스택 영역, 힙 영역으로 구분된다.

Image

메서드 영역

메서드 영역은 클래스 정보를 관리한다. 이 클래스 정보가 붕어빵 틀이다. 클래스 정보에는 클래스 이름, 상속 관계, 메소드, 변수 정보 등이 포함된다. 이 영역은 프로그램이 시작될 때 생성되고, 프로그램이 종료될 때까지 유지된다.

클래스 정보 뿐만 아니라, 메서드 영역에서는 프로그램을 실행하는데 필요한 공통 데이터를 관리하고, 이 영역은 모든 영역에서 공유한다.

  • 클래스 정보
    • 클래스의 실행 코드(Byte 코드), 필드, 메서드, 생성자 코드 등 모든 실행 코드 존재
  • static 영역
    • static 변수들을 보관
  • 런타임 상수 풀
    • 프로그램을 실행하는데 필요한 공통 리터럴 상수 보관

스택(Stack) 영역

스택 영역은 실제 프로그램이 실행되는 영역이다. 메서드를 실행할 때마다 하나씩 쌓인다. 즉, 스택 영역은 메서드가 호출될 때마다 새로운 프레임이 생성되고, 메서드가 종료되면 해당 프레임이 제거된다. 이 영역은 메서드의 지역 변수와 매개 변수를 저장한다. 스택 영역은 가장 마지막에 실행된 메서드 프레임이 가장 먼저 종료되는 LIFO(Last In First Out) 구조로 동작한다.

자바 실행 시 , 하나의 실행 스택이 생성되고, 각 스택 프레임은 지역 변수, 중간 연산 결과, 메서드 호출 정보 등을 포함한다.

  • 스택 프레임
    • 메서드를 실행할 때마다 하나의 스택 프레임이 쌓이고, 메서드가 종료되면 해당 스택 프레임이 제거된다.

힙(Heap) 영역

객체(인스턴스)가 생성되는 영역이다. 객체를 생성할 때, 사용하는 new 명령어를 사용하면 이 영역을 사용하는 것이다. 예를 들면 붕어빵 틀로부터 생성된 붕어빵이 존재하는 공간이라고 할 수 있다. 정리해보자면 힙 영역은 객체와 배열이 생성되는 영역이고, 가비지 컬렉션이 이루어지는 주요 영역이다. 더 이상 참조하지 않는 객체는 가비지 컬렉션에 의해서 메모리에서 제거된다.

정리

Image

만약, 자바에서 특정 클래스에 대한 new 명령어를 사용하여 100개의 인스턴스(객체)를 생성했다면, 힙 메모리에 100개의 인스턴스가 생긴다. 각각의 인스턴스는 내부에 필드 변수와 메서드가 존재한다. 여기서 내부 필드 변수에 저장되는 값은 인스턴스마다 다를 수 있지만, 메서드의 기능은 동일하다. 따라서, 객체가 생성될 때, 인스턴스 변수에는 메모리가 할당되지만, 메서드에 대한 새로운 메모리 할당은 없으며 이는 메서드 영역에서 공통으로 관리한다.

스택 영역과 힙 영역

스택 영역

자바는 스택 영역을 사용해서 메서드 호출과 지역 변수를 관리한다. 메서드를 계속 호출하면 스택 영역에 스택 프레임이 계속 쌓이고, 이 스택 프레임들에 각 메서드에서 활용되는 지역 변수 정보와 매개변수 정보들이 포함되어 있다.

따라서, 스택 프레임이 종료되면 지역 변수도 함께 제거되고, 모든 스텍 프레임이 제거되면 프로그램도 종료된다.

  • 지역 변수 => 스택 영역

힙 영역

힙 영역은 객체와 배열이 생성되는 영역이다. 자바에서 객체를 생성할 때는 new 키워드를 사용한다. 이때, 힙 영역에 메모리가 할당되고, 해당 객체의 인스턴스가 생성된다. 이런 힙 영역에 있는 객체 중 더 이상 어떤 스택 변수나 다른 객체에서도 참조되지 않을 때, 가바지 컬렉션 대상이 되어 메모리에서 해제된다.

  • 객체(인스턴스) 및 배열 => 힙 영역

static

static 키워드는 클래스 레벨에서 공유되는 변수나 메서드를 정의할 때 사용된다. static 변수와 static 메서드는 클래스가 로드될 때 메모리에 할당되며, 인스턴스가 생성되지 않아도 클래스명으로 접근할 수 있다. 다시 말해서, static 변수는 클래스의 모든 인스턴스에서 공유되며, static 메서드는 클래스의 인스턴스 없이 호출할 수 있다.

static 변수

static 변수는 인스턴스가 아닌 클래스 레벨에서 관리되며, 메서드 영역 안의 static 영역에 저장된다. 모든 인스턴스가 동일한 static 변수를 공유하기 때문에, 클래스의 모든 인스턴스에서 동일한 값을 가지게 된다. static 변수는 클래스가 로딩될 때, 딱 하나만 생성되어 모든 인스턴스가 공유한다. 그렇기 때문에 static 키워드가 붙은 변수를 클래스 변수라고도 한다. static 키워드가 없는 일반 필드 변수를 인스턴스 변수라고 한다.

static 메소드

static 메서드는 static 변수와 마찬가지로 인스턴스를 생성하지 않고도, 클래스 이름으로 직접 호출할 수 있는 정적 메서드이다. 정적 메서드는 언제나 사용할 수 있는 것이 아니라 특별한 사용법이 존재한다.

  • static method 사용법
    • 객체 생성없이 클래스 이름으로 직접 호출 가능하다.
    • static 메서드는 static만 사용할 수 있다.
      • 클래스 내부의 기능을 사용할 때, 정적 메서드는 static이 붙은 정적 메서드정적 변수만을 사용할 수 있다.
      • 클래스 내부의 기능을 사용할 때, 인스턴스 메서드인스턴스 변수는 사용할 수 없다.
    • 반대로 모든 곳에서는 static 메서드를 사용할 수 있다.

이렇게 static 키워드가 붙은 메서드를 클래스 메서드라고 하며, 정적 메서드라고도 부른다. 반대로 static 키워드가 없는 메서드를 인스턴스 메서드라고 한다. 인스턴스 메서드는 객체를 생성해야지만 호출하여 사용할 수 있고, 클래스 메서드는 객체를 생성하지 않고도 클래스 이름과 .(dot) 연산자를 통해서 호출할 수 있다.

이러한 정적 메서드는 객체 생성이 필요 없이 메서드의 호출만으로 필요한 기능을 수행할 때 주로 사용한다. 예를 들어, 간단한 메서드 하나로 긑나는 유틸리티성 메서드에 자주 사용한다.

정적 메서드가 인스턴스의 기능을 사용할 수 없는 이유

Image

정적 메서드는 클래스 레벨에서 동작하기 때문에, 인스턴스의 상태(인스턴스 변수)를 알 수 없다. 즉, 정적 메서드는 인스턴스에 종속되지 않기 때문에, 인스턴스 변수나 인스턴스 메서드를 사용할 수 없다. 간단하게 말하면, 특정 인스턴스의 기능을 사용하기 위해서는 해당 인스턴스의 참조값(주소)을 알아야 하는데, 정적 메서드는 참조값 없이 호출하기 때문에 인스턴스 변수나 인스턴스 메서드를 사용할 수 없다.

변수와 생명주기

  • 지역 변수

    • 지역 변수는 스택 영역에 있는 스택 프레임 안에 보관된다. 따라서 메서드가 종료되면 스택 프레임도 제거되는데, 이때 해당 스택 프레임과 함께 지역 변수도 제거된다. 즉, 지역 변수의 생존 주기는 짧다고 할 수 있다.
  • 인스턴스 변수

    • 클래스에 대한 new 명령어로 객체가 생성되고, 이 객체가 가지고 있는 필드 변수가 인스턴스 변수이다. 인스턴스 변수는 힙 영역에 저장되고, 힙 영역에서 GC(가비지 컬렉터)가 발생하기 전까지는 생존하기 때문에 보통 지역 변수보다 생존 주기가 길다.
  • 클래스 변수

    • 클래스 변수는 인스턴스 변수 앞에 static 키워드가 붙은 필드 변수이다. 클래스 변수는 메서드 영역의 static 영역에 저장되며, 클래스가 JVM에 로딩되는 순간 생성되고, JVM이 종료될 때까지 유지된다. 따라서 클래스 변수의 생존 주기는 가장 길다.