[JAVA] 메모리 (Stack/Heap)

김정민·2024년 10월 30일
2
post-thumbnail

자바가 실행이되면 JVM은 메모리를 할당받고 그 메모리를 용도에 따라서 나누어 관리한다.

JVM의 메모리 공간이 어떻게 나누어지고 관리되는지 알아보고 차이점을 알아보자.

💡 자바 변수의 종류

변수는 크게 네종류로 변수의 선언된 위치에 따라서 클래스변수, 인스턴스변수, 지역변수, 매개변수로 구분된다.

public class Main {
	
    public static void main(String[] args) { // 매개변수
    	int num = 990; // 지역변수
	}
}

public class Counter {
	private int state = 0; // 인스턴스 변수
    
    public static int gade = 100; // 클래스 변수
    
    public int get() {
    	return state;
}

각 변수의 생성시기

클래스변수 : 클래스가 메모리에 올라갈 때
인스턴스변수 : 인스턴스가 생성되었을 때
지역변수 / 매개변수 : 위치하고 있는 메서드가 수행되었을 때

💡 Stack 메모리

  • 메소드 내에서 정의하는 기본 자료형에 해당되는 지역변수의 데이터 값이 저장되는 공간
  • 메소드가 호출될때 스택 영역에 스택 프레임이 생기고 그안에 메소드를 호출
  • 메소드가 호출 될 때 메모리에 할당되고 종료되면 메모리에서 사라짐
  • Stack 은 후입선출 LIFO(Last-In-First-Out) 의 특성을 가지며, 스코프(Scope) 의 범위를 벗어나면 스택 메모리에서 사라진다.

아래의 예제로 이해 해보자.

public class Main {
	public static void main(String[] args) {
    	int a = 100;
        a = wow(a);
    }
    
    public static int wow(int num) {
    	int b = num * 4;
        return b;
    }
}

위 예제를 그림으로 그려보자.

public class Main {
	public static void main(String[] args) {
    	int a = 100;
        a = wow(a);
    }

전체 코드 중 위 코드 영역 Stack은 주황색으로 표현하였고 아래 코드 영역은 초록색으로 표현하였다.

변수 args와 a를 Stack에 담고 wow 함수를 Stack에 담았다. 함수 호출 시 a의 값을 넣어주기 때문에 매개변수인 num은 100이 대입되는 모습을 표현한 결과이다.

    public static int wow(int num) {
    	int b = num * 4;
        return b;
    }

초록색 영역에서 num * 4 결과인 b를 Stack에 저장한다.

wow 함수의 결과를 return하고 a에 저장을 해주므로 초록색 스택은 사라지게된다.

실행 후 결과는 아래와 같이 나타난다.

Stack 메모리는 변수들이 저장되고 메서드 함수가 호출될 때 마다 쌓이는 방식으로 동작한다.

💡 Heap 메모리

  • JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역
  • 참조형(Reference Type) 데이터 타입을 갖는 객체(인스턴스), 배열 등이 저장 되는 공간
  • 단, Heap 영역에 있는 오브젝트들을 가리키는 레퍼런스 변수는 stack에 적재
  • Heap 영역은 Stack 영역과 다르게 보관되는 메모리가 호출이 끝나더라도 삭제되지 않고 유지된다.
  • 어떤 참조 변수도 Heap 영역에 있는 인스턴스를 참조하지 않게 된다면, GC(가비지 컬렉터)에 의해 메모리에서 청소된다.

아래의 예제로 이해 해보자.

public class Main {
	public static void main(String[] args) {
    	Counter c = new Counter();
        two(c);
        int count = c.get();
    }
    
    public static int two(Counter c) {
    	c.increment();
    	c.increment();
    }
}

public class Counter {
	private int state = 0;
    public void increment() { state++; }
    public int get() { return state; }
}

예제를 그림으로 그려보자.

변수들을 저장하고 생성된 객체는 heap 메모리에 저장하고 객체를 생성한 c는 주소값을 저장하게 된다.

갈색은 two 함수의 Stack이다. c를 넘겨주었으므로 동일한 주소값을 가진 heap메모리에 접근한다.

살색은 increment 함수의 Stack이다. 동일한 주소값을 가진 heap 메모리에 접근하여 state++를 실행한다. 2번 실행한 결과의 그림이다.

위 그림은 two 함수가 실행되고 나서 Stack을 빠져나온 모습이다.

파란색은 get 함수의 Stack이다. 같은 주소값을 따라가서 2를 반환 받게 된다.

반환 받은 state를 count 변수가 저장하면서 마무리가 된다.

위 예제를 분석한 결과는 호출된 함수나 메서드가 파마미터를 객체를 받게되어 변경을 한다면 그 변경된 상태를 남아있는 것이다.

💡 가비지 컬렉터(GC)

  • 가비지 컬렉터는 힙 영역에 참조되지 않고 남아버린 객체들을 식별해 힙 영역을 청소 해주는 역할을 한다.

가비지 컬렉터의 대상이 되는 객체는 무엇인지 확인해보자.

public class Main {
	public static void main(String[] args) {
    	Counter c = make();
    }
    
    public static Counter make() {
    	Counter c = Counter();
        return new Counter();
    }
}

public class Counter {
	private int state = 0;
    public void increment() { state++; }
    public int get() { return state; }
}

이것도 그림으로 그려보면서 이해 해보자.

Stack, Heap의 메모리는 위 그림와 같이 저장될 것이다.

변수 c가 바라보는 객체는 2번째로 생성된 객체를 가르키게 될 것이고 1번째로 생성된 객체는 힙 영역에 참조되지 않고 남아버린 객체가 된다.

GC(가비지 컬렉션)은 이렇게 참조 되지 않고 남아버린 객체를 청소해준다.

Stack, Heap의 차이점

  • 힙 메모리는 애플리케이션의 모든 부분에서 사용되며, 반면에 스택 메모리는 하나의 스레드가 실행될 때 사용.
  • 언제든지 객체가 생성되면 항상 힙 공간에 저장되며, 스택 메모리는 힙 공간에 있는 객체를 참조만 한다.
  • 스택메모리의 생명주기는 매우 짧으며, 힙 메모리는 애플리케이션의 시작부터 끝까지 살아남는다.
  • 자바 코드를 실행할때 따로 -Xms과 -Xmx 옵션을 사용하면 힙 메모리의 초기 사이즈와 최대 사이즈를 조절할 수 있다.
  • 스택 메모리가 가득차면 자바에서는 java.lang.StackOverFlowError를 발생.
  • 힙 메모리가 가득차면 java.lang.OutOfMemoryError : Java Heap Space 에러를 발생
  • 스택 메모리 사이즈는 힙 메모리와 비교했을 때 매우 적다. 하지만 스택 메모리는 간단한 메모리 할당 방법(LIFO)를 사용하므로 힙 메모리보다 빠르다.

마무리

지금까지 Stack, Heap 메모리에 대해서 모호하게 알고 있었다. 이번 포스팅 기회로 어떻게 동작하는지 어떤 데이터들이 가비지 컬렉터에의해 청소가 되는지 알게 되었다.


출처: https://inpa.tistory.com/entry/JAVA-☕-그림으로-보는-자바-코드의-메모리-영역스택-힙#힙_과_스택_메모리의_차이점 [Inpa Dev 👨‍💻:티스토리]

출처 : https://www.youtube.com/watch?v=GIsr_r8XztQ [쉬운코드 - 변수와 객체와 메모리의 관계! 자바를 예로 들어 변수와 객체는 메모리에 어떻게 저장되는지 정말 쉽게 설명해요!]

1개의 댓글

comment-user-thumbnail
2024년 10월 30일

stack과 heap에 대해서 개념 잘 세기고 갑니다!👍

답글 달기