Java 데이터 저장 영역 (스태틱, 스택, 힙)

권광재·2024년 2월 23일

java

목록 보기
5/6

들어가기 전

이전 포스트에서 데이터 저장 영역인 런타임 데이터 영역에 대해서 말한 적이 있다.

Runtime Data Area(런타임 데이터 영역, 메모리 영역): JVM이 프로그램을 실행하는 동안 데이터를 저장하는 메모리 영역

그렇다면 이러한 데이터는 어떠한 형식으로 저장이 되는 것인가?

하지만 알아보기 전에 사전지식으로 알아야 할 내용들이 있다.
바로 우리가 단축키로써 사용하는 psvm,sout이다.

public static void main(String[] args)

public: main 메서드가 외부에서 접근 가능하도록 지정
static: main 메서드가 인스턴스화되지 않고 클래스 수준에서 호출
void: main 메서드가 반환하는 값의 타입이 없음
main: 메서드의 이름(
String[] args: 명령행 인수를 전달 받는 매개변수

main이란 이름을 가진 메서드는 사실상 단 하나만 존재하고 자바 프로그램이 시작되는 지점이다.

System.out.println()

메서드 영역에 포함되는 내용이다.
그렇기에 heap영역에서의 메모리를 통제하는 가비지 컬렉터와는 연관이 없다.

1. 스태틱, 스택, 힙?

먼저 런타임 데이터 영역에서 설명한 내용을 보면

스택 영역(Stack Area): 각 스레드마다 생성되는 공간으로, 메서드 호출 시 지역 변수, 매개변수, 메서드 호출 정보 등을 저장
메서드 영역(Method Area): 클래스에 대한 메타데이터(클래스의 구조, 필드, 메서드 등)를 저장하는 공유 메모리 영역
힙 영역(Heap Area): 객체 인스턴스와 배열 등이 저장되는 공간으로, 가비지 컬렉션의 대상이 되는 영역

이렇게 정의가 되어있다. 스태티그 스택, 힙도 별 다를 내용이 없다.

static 영역: 클래스들의 놀이터
stack 영역: 메서드들의 놀이터
heap 영역: 객체들의 놀이터

이렇게 간단하게 생각하여도 된다.

그렇다면 예시를 통해 알아보자
예시는 책 스프링입문을 위한 자바 객체지향의 원리와 이해에서 가져왔다.

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

main() 메서드가 실행되기 전 JVM에서 수행하는 전처리 작업들
1. java.lang 패키지를 T 메모리의 스태틱 영역에 배치
2. import된 패키지를 T 메모리의 스태틱 영역에 배치
3. 프로그램 상의 모든 클래스를 T 메모리의 스태틱 영역에 배치 

이렇게 하면 이제 스택 영역을 받아들일 준비가 된 것이다. (클래스 정의를 시작하는 중괄호를 빼고 여는 중괄호를 만날 때마다 스택 프레임이 하나씩 생긴다.)

T메모리는 세 개의 영역이 있는데 변수는 스태틱, 스택, 힙 중 어디에 있나?
이 질문의 답은 세 군데 모두 이다. 세 군데 각각에 있는 변수는 각기 다른 목적을 가져 이름도 , 클래스 멤버 변수 지역 변수, 객체 멤버 변수라고 한다.

클래스 멤버 변수:스태틱 영역에 있다. 한번 실행되면 JVM이 종료될 때까지 고정된 상태로 존재한다.
지역 변수: 스택 영역에 있다. 따라서 스택 프레임이 사라지면 함께 사라진다.
객체 멤버 변수: 힙에 있다. 객체와 함께 GC에 의해 관리된다.

2. 알아야할 것

이 내용들을 통해 알아야 할 큰 부분은 멀티 스레드와 전역 변수에 대한 내용이다.
전역 변수는 static 영역에 저장도는 변수에 대해서 말하는 것이고, 멀티 스레드는 각 프로세스마다 각자의 T메모리를 가지고 있는 멀티 프로세스와 다르게 하나의 T메모리만 사용하여 스택 영역만 분할해서 사용하는 구조이다.
스택만 분할을 하였기 때문에 하나의 스레드에서 다른 스레드의 스택 영역은 접근 불가지만 스태틱 영역과 힙 영역은 공유해서 사용하는 구조이다.

서블릿은 요청당 프로세스가 아닌 요청당 스레드를 생성한다.

그럼 이제 이것을 통한 장점이 생기지만 단점도 생긴다.

전역 변수 A에 10을 할당(스레드 1) -> 전역 변수 A에 20을 할당(스레드 2) -> 전역 변수 A의 값을 스레드 1이 출력 -> 20이 출력

이렇게 출력상의 오류가 발생한다.

그래서 전역 변수를 쓰지 말라는 말이 나오는 것이다. 이를 보완하는 방법으로 lock을 거는 방법이 있지만 쓰는 순간 멀티 스레드의 장점이 버려지는 문제가 있다.

멀티 쓰레드의 단점인 race condition(경쟁 상태)에 대해서 알아보는 것도 추천한다.

profile
안녕하세요

0개의 댓글