WeakRefrence에 대한 이해를 돕기 위해 GC 동작에 대해 간략히 알아보자
GC(Garbage Collection) 동작
GC(Garbase Collection)는 프로그래머가 명시적으로 메모리를 할당하거나 해제하지 않아도 자동으로 메모리 관리를 제공해주는 편의성을 가지게 해준다.
GC의 동작은 매우 다양하지만 아래 핵심 동작은 모든 GC 알고리즘에서 공통적으로 이뤄지고 있는 내용이다.
(1) Heap 내의 객체 중 사용되지 않는 객체를 찾는다
(2) 사용되지 않는 객체의 Memory를 회수한다.
이에 좀 더 나아가면 GC는 객체가 가비지인지 아닌지를 판별하기 위해서 rechability라는 개념을 사용한다.
어떤 객체가 참조되고 있는 곳이 한곳이라도 있을 경우 rechable로 구별되며, 반대로 참조되고 있는 곳이 하나도 없으면 unrechable로 구별된다.
즉, GC는 unrechable 객체를 가비지로 인식하고 메모리를 해제한다.
Process의 원활한 Memory 관리를 위해 프로그래머는 사용이 완료 된 객체의 참조를 끊어 unrechable 객체로 만들 수 있도록 유념해야한다.
Garbage Collection에 대해 더알고 싶다면 아래 링크를 참조하자
https://jtm0609.tistory.com/171
[Java] Garbage Collector (GC)
Garbage Collection(GC) 이란?가비지 컬렉션(Garbage Collection, 이하 GC)은 자바의 메모리 관리 방법 중의 하나로 JVM(자바 가상 머신)의 Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객
jtm0609.tistory.com
Refrence
대표적인 Refence의 종류는 아래와 같이 분류를 할 수 있다.
- Strong Refrence
- Weak Refrence
- Soft Refrence
GC가 메모리를 정리할 대상인지 판단하기 위해서 rechability라는 기준을 가지고 있다.
StrongRefrence의 경우 rechability에 의해서 기준은,
가장 먼저 참조되어지는 root 객체로부터 사슬이 계속 연결되어 있는가의 여부이다.
이 사슬이 끊어져 있다면, unrechable로 보고, GC의 메모리 회수 대상이 되는 것이다.
반면에 약한 참조의 경우 명확하게 GC에 의해 메모리 상의 회수대상이 되어진다.
강한참조 (Strong Refrence)
- 강한 참조는 Java의 기본 참조 유형으로 new를 통해 객체를 생성할 때 생기게 되는 참조이다.
- 강함 참조를 통해 참조되고 있는 객체는 참조가 해제되지 않는 이상 가비지 컬렉터의 대상에서 제외된다.
- 강한 참조에 의해, 참조하고 있는 원본 객체를 null로 설정하여도 GC가 수거해가지 않는다.
아래 2가지 예시를 보고 이해를 해보자
강한 참조 (GC 수거 대상)
public class StrongReferenceExample {
public static void main(String[] args) {
// 'root'가 Strong Reference를 가지고 'obj1'을 참조
Example obj1 = new Example("Object 1");
// obj1을 root 객체에서 참조하는 상태에서 obj1은 여전히 reachable
System.out.println("Before dereferencing:");
obj1.printName(); // Object 1 출력
// 'root' 객체에서 obj1의 참조를 끊음
obj1 = null;
// obj1을 더 이상 참조하지 않으므로 이제 obj1은 unreachable 상태가 된다.
System.out.println("After dereferencing:");
// obj1은 이제 null이므로 호출하면 NullPointerException이 발생함
// obj1.printName(); // Uncommenting this will cause NullPointerException
// 이제 GC에 의해서 obj1 객체는 메모리에서 회수될 수 있다.
}
}
obj1 코드를 null로 설정함으로서 더이상, 참조하는 객체가 아니게 된다. 이로써 unrechable 상태가 되고 GC에 의해 수거가 된다.
강한 참조 (GC 수거 대상X)
public class StrongReferenceExample {
public static void main(String[] args) {
// 'root'가 Strong Reference를 가지고 'obj1'을 참조
Example obj1 = new Example("Object 1");
// obj1을 obj2에 강한 참조로 할당
Example obj2 = obj1;
// obj1과 obj2는 동일한 객체를 참조하므로 두 변수 모두 같은 객체를 가리킴
System.out.println("Before dereferencing obj1:");
obj1.printName(); // Object 1 출력
obj2.printName(); // Object 1 출력 (obj2도 동일 객체를 참조)
// obj1에 대한 참조를 끊음
obj1 = null;
// 이제 obj1은 null이 되어 더 이상 해당 객체를 참조하지 않지만,
// obj2는 여전히 동일 객체를 참조하므로 해당 객체는 reachable 상태
System.out.println("After dereferencing obj1:");
obj2.printName(); // Object 1 출력 (여전히 obj2가 해당 객체를 참조)
// obj1은 더 이상 참조하지 않지만, obj2가 여전히 객체를 참조하고 있으므로
// GC는 이 객체를 회수하지 않음
}
}
원본 객체인obj1을 null로 설정했지만, obj2가 여전히 강한참조로 인해 참조를하고 있기 때문에 rechable상태가 되며, GC에 의해 수거되지 않는다.
약한 참조 (Weak Refrence)
- 약한 참조는 Java의 lang 패키지의 WeakrRefrence 클래스를 사용하여 생성한다.
- 약한 참조는 GC가 발생하면 수거된다.
- 참조하고 있는 원본 객체를 null로 설정 하면 GC가 원본 객체를 수거해가고, WeakRefrence 객체에 대한 참조가 null 값으로 처리가 된다.
예를 들어, 아래처럼 WeakRefrence를 선언하는 코드가 있을 때,
mStudent 객체에 null을 대입해주면 Strudent 객체에 대한 접근은 WeakRefrence인 mWeak를 통해서만 가능하게 된다. 이렇게 WeakRefrence에 의해서만 접근할 수 있는 상태가 되었을 때,
Rechability가 약하다고 할 수 있는데,
이 상태가 되면 GC 동작 시에 WeakReference 객체에 대한 참조를 null 값으로 해주기 때문에 GC에 의해서 메모리 상에 정리되는 대상이 될 수 있는 것이다.
언제 Weak Refrence를 하면 좋을까?
캐시 시스템에서 사용:
- 캐시된 데이터는 그 자체로 중요하지 않지만, 성능을 높이기 위해 메모리 내에 보관됩니다. 만약 시스템이 메모리를 많이 사용하는 상황이 오면, GC가 캐시된 객체를 회수하게 하여, 캐시 데이터를 자동으로 청소하도록 할 수 있다.
메모리 부족할 때 캐싱 데이터가 없어지더라도 재요청하여 가져오면 되는 것이겠죠? 물론 캐싱 데이터가 날아가지 않도록 해야하는 중요한 데이터라면, WeakRefrence를 쓰면 안되겠죠
메모리 관리가 중요한 상황에서 사용:
- 메모리 자원이 제한된 환경에서, 특정 객체가 더 이상 필요하지 않을 때 GC가 이를 회수하도록 유도하여 메모리를 절약할 수 있다.
Soft Refrence
- Soft 참조는 강한참조와 약한 참조와는 다르게 GC에 의해 수거될 수도 있고, 수거되지 않을 수도 있다.
- 메모리에 충분한 여유가 있다면 GC가 수행된다 하더라도 수거되지 않는다. 하지만 메모리가 부족하면 수거될 확률이 높다.
예제
위 3가지 개념을 적용한 간단한 예제를 살펴보자.
public class ReferenceTest {
public static void main(String[] args) {
Fruit apple = new Fruit("사과");
Fruit banana = new Fruit("바나나");
Fruit strong = apple;
WeakReference<Fruit> weak = new WeakReference(banana);
apple = null;
banana = null;
//GC 실행
System.gc();
System.out.println(apple == null ? "null" : apple.name);
System.out.println(banana == null ? "null" : banana.name);
System.out.println(strong == null ? "null" : strong.name);
System.out.println(weak == null ? "null" : weak.get());
}
private static class Fruit {
private String name;
public Fruit(String name) {
this.name = name;
}
}
}
apple을 참조하고 있던 strong 객체는 apple의 참조가 해제되었음에도 불구하고 사과를 출력한다.
하지만 banana를 참조하고 있던 weak 객체는 banana의 참조가 해제되니 null을 출력하는 것을 볼 수 있다.
즉, strong은 강함 참조이기 때문에 원본에 null을 넣어 참조를 해제해줘도, string이 참조하고 있으므로 객체가 해제되지 않았다.
반면에 weak는 약한참조이기 때문에 원본에 null을 넣어 참조를 해제해주니 weak가 참조하고 있어도 객체가 해제되었다.
참고자료
https://roomenergy.tistory.com/49
[Java] 강한 참조(Strong Reference)와 약한 참조(Weak Reference)
강한 참조(Strong Reference) 강한 참조는 Java의 기본 참조 유형으로 new를 통해 객체를 생성할 때 생기게 되는 참조다. 강함 참조를 통해 참조되고 있는 객체는 참조가 해제되지 않는 이상 가비지 컬
roomenergy.tistory.com
WeakReference <약한 참조> 에 대해서 정리해보자
앱 개발이 마무리 단계에 들어서서, 테스트하면서 부딪히는 문제가 바로 MemoryLeak입니다.MemoryLeak(메모리 누수)가 나는데는 여러가지 문제가 있습니다만.해결책으로 종종 제시되는 것이 WeakReferenc
developer88.tistory.com
Java GC 동작 방식과 WeakReference의 이해
예전에 한번 Java 메모리 관련 내용을 포스팅 ([Java/Android] Memory Leak을 발생시키는 기본 유형) 한적이 있지만, 갑작스럽게 Java WeakReference 동작 방식이 궁금하게 되어 본 포스팅을 작성하게 되었다. 1
velog.io
https://d2.naver.com/helloworld/329631
'Java' 카테고리의 다른 글
[Java] 스레드 생명주기와 스케줄링 (0) | 2025.01.28 |
---|---|
[Java] Throwable vs Error vs Exception 그리고 예외 처리 전략 (0) | 2025.01.14 |
[Java] static 블록과 생성자 (1) | 2024.12.14 |
[Java] 기본타입 vs 참조타입 (1) | 2024.06.10 |
[Java] 추상 클래스 vs 인터페이스 (0) | 2024.06.10 |