"여기서 리스트라는 객체가 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
'java' 카테고리의 다른 글
[JAVA] AtomicInteger, 쓰레드 동기화(synchronization) , Atomic, CAS 알고리즘 이해하기 (0) | 2021.08.28 |
---|---|
[JAVA] - 변수(Variable) (0) | 2021.08.14 |
[JAVA]Garbage Collection 실행 과정 (0) | 2021.08.07 |
[자바 병렬 처리 - 포크/ 조인 프레임 워크] (0) | 2021.04.17 |
[JAVA]스트림(Stream) 에서 기본형(Primitive type)은 왜 취약할까? (0) | 2021.04.13 |