본문 바로가기

java

[JAVA] 객체 메모리 할당 - Stack, Heap, GC

[10분 테코톡] 던의 JVM의 Garbage Collector

 

"여기서 리스트라는 객체가 stack에서 names 라는 변수가 참조를 하고 있고 또 이 객체(List) 가 각 String 객체를 참조 하고 있는 경우가 있고 이 던(String) 은 참조를 받고 있지 않기 때문에 이 객체는 Unrechable Object 이고 던 영역이 Garbage Collector 를 통해서 해제되게 됩니다." 

 

이 부분 헷갈렸다. 객체의 메모리 할당이 어떻게 되는지 위주로 이어서 정리한다. 아래 내용은 모두 인용(아래 출처에서)된 것이다. 

 

1. Stack 과 Heap 의 차이

 

1) Stack 

- 원시 타입의 데이터가 값과 저장 ( int, boolan, double 등의 실제 값이 스택에 할당) 

- Heap 영역에 생성된 Object 타입의 데이터 참조값이 저장 

- 함수가 호출될 때 사용하는 메모리이고 기능 수행이 끝나면 자동으로 반환되는 메모리

 

Stack 은 후입선출(LIFO) 의 특성을 가지며 스코프(Scope) 의 범위를 벗어나면 스택 메모리에서 사라진다.

중괄호(brace) 시작과 끝, 즉 중괄호 내부가 범위가 된다. 예를 들면 while,if, for 의 중괄호

중괄호 안의 값은 그 범위를 벗어나면 스택에서 사라지게 된다. (닫는 중괄호가 실행 되는 순간, 현재 할당된 스택 메모리는 사라지게 된다. 

 

 

2. Heap 

- Object 타입의 데이터가 저장 (String, Interger 등의 Object 타입)  

- 애플리케이션의 모든 메모리 중 Stack 을 제외한 부분 

- 자동으로 관리되지 않은 메모리 영역 (CPU 가 엄격하게 관리하지 않는다)

- GC가 관리 해준다.

 

Heap은 instance 객체가 제거되기 전까지 스코프와 상관없이 값이 유지된다. stack 메모리에 있는 값은 스코프를 벗어나면 값이 상실되지만 c/c++ 에서 힙에 생성된 값은 생성하면 개발자가 직접 제거 해야한다. (C#이나 JAVA 는 GC 할당) 

 

 

 

3. stack 메모리 할당 과정 살펴보기 

public class Stack {
	public static void main(String[] args) {
    	int num1 = 20; 
        int num2 = 30; 
        int sum = 0; 
        
        sum = addNum(num1, num2) 
        System.out.pringln(sum);
    }
    
    public static int addNum(int n1, int n2) {
    	int result = n1 + n2; 
        return result;
    }
}

 

<그림 상세설명> 

stack1(1) - 메인 함수가 호출 되면 num1, num2,, sum 이라는 변수의 이름으로 stack에 메모리가 할당됩니다. 또한 변수의 타입이 원시타입이기 때문에 실제값도 같이 할당 됩니다. 

stack(2) - addNum 함수가 호출이 되면 인자로 num1 과 num2 의 변수를 넘겨준다.  또한 스코프가 addNum 함수를 이용한다. 스코프가 변경되면 기존의 sum, num2, num1 은 사용할 수 없게된다. n1, n2, result 의 데이터 타입으로 스택 영역 공간에 할당이 된다. 

stack(3) - addNum의 함수 호출이 종료가 되면 함수 호출시에 사용되었던 모든 지역 변수는 스택 영역에서 사라지게 된다. 함수 호출이 사라지기전에 재 할당이 되어 sum 은 50으로 변환된다. 

stack(4) - main 함수까지 종료가 되면 stack 에 있던 모든 데이터들이 사라지면서 프로그램이 종료된다.

 

 

4. Heap 메모리 할당 과정 살펴보기 

 

public class Stack {
	
    public static void main(String[] args) {
    	int age = 19; 
        String name = "Sejin Hong"
    }
}

 

 

<그림 상세설명> 

1. age 는 원시타입이기 때문에 값과 함께 stack에 할당이 됩니다. String은 Object 를 상속받아 구현되는 것이기 때문에 Heap 영역에 할당 된다. stack 에 name 이라는 이름으로 생성된 변수는 Heap 에 있는 Sejin Hong 이라는 String을 reference 하게 된다. 

 

 

 

 

5. Garbage Collection

 

public class Stack {
	public static void main(String [] args) {
    	String url = "https://"; 
        url += "sejin.com";
    }
}

 

 

 

다음 구문을 실행해 보면 문자열이 합쳐지는 과정에서 기존에 있던 url에 합쳐지는 것이 아니라 새로운 Object 를 생성하게 되고 새로운 Heap 영역을 할당하게 된다. (참조 하고 있는 값이 없기 때문에 unreachable Object 가 된다.)

* unrachable Object : Stack 에 도달할 수 없는 Heap 영역

- JVM 의 가비지 컬렉터는 unreachable Object를 힙 영역에서 제거한다. 

 

 

 

출처: 
https://novemberde.github.io/2017/04/15/String_0.html
https://www.youtube.com/watch?v=8aH54mBTVLQ 
https://postitforhooney.tistory.com/entry/JavaStackHeap-JAVA%EC%9D%98-Stack%EA%B3%BC-Heap%EC%9D%98-%EC%9D%B4%ED%95%B4%EB%A5%BC-%ED%86%B5%ED%95%B4-Java%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC

 

반응형