Java
[JAVA] WeakReference, SoftReference 사용법
teamnova
2025. 2. 23. 20:40
728x90
안녕하세요,
오늘은 메모리 누수 방지를 위한 WeakReference, SoftReference 사용법에 대해 알아보고자 합니다.
먼저, 참조(Reference)란, 객체의 메모리 주소를 가리키는 변수를 의미합니다.
Java에서 모든 객체(클래스의 인스턴스)는 참조를 통해 접근하고,
참조가 없으면 해당 객체는 더 이상 사용할 수 없습니다.
Java의 참조(Reference)는 4가지 종류가 있습니다.
- StrongReference
- 기본적인 java 객체의 참조 형식, new를 통해 객체를 생성하는 경우의 참조 형식
- GC가 제거하지 않음 (명시적으로 null 할당해야 해제됨)
- WeakReference
- JVM의 Garbage Collector(GC)가 더 쉽게 객체를 수거할 수 있도록 하는 참조 타입
- GC가 필요할 때 즉시 객체를 제거하는 참조(GC가 실행되면 거의 즉시 삭제됨)
- SoftReference
- 메모리가 부족할 때만 GC가 객체를 제거하는 참조
- WeakReference보다 객체를 오래 유지할 수 있음.
- 메모리가 충분하면 객체가 유지되지만, 메모리가 부족하면 GC가 객체를 제거함
- PhantomReference
- 객체가 GC에 의해 제거된 후에도 참조를 유지할 수 있는 방식
- 객체가 완전히 제거된 후 후처리 작업이 필요할 때 사용됨
- get()을 호출해도 원래 객체를 반환하지 않음 (항상 null)
위 4가지 참조 중 WeakReference 와 SoftReference 참조 해제를 해보겠습니다.
참조 해제 예제코드
import java.lang.ref.WeakReference;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
public class ReferenceExample {
public static void main(String[] args) throws InterruptedException {
// WeakReference 생성
WeakReference<String> weakRef = new WeakReference<>(new String("WeakReference 객체 텍스트"));
// SoftReference 생성
SoftReference<String> softRef = new SoftReference<>(new String("SoftReference 객체 텍스트"));
// 참조 객체 출력
System.out.println("weakRef 값: " + weakRef.get());
System.out.println("softRef 값: " + softRef.get());
// GC 실행 요청
System.gc();
// GC 실행 후 결과 출력
System.out.println("\n==== GC 실행 후 ====");
System.out.println("weakRef 값: " + weakRef.get()); // GC가 제거 가능
System.out.println("softRef 값: " + softRef.get()); // 메모리가 충분하면 유지됨
// 💡 메모리 부족 강제 발생: 여러 개의 큰 배열을 할당하여 메모리 부족 유도
List<byte[]> memoryList = new ArrayList<>();
try {
for (int i = 0; i < 1000; i++) {
memoryList.add(new byte[10 * 1024 * 1024]); // 10MB씩 할당
System.out.println("메모리 사용 증가: " + (i + 1) * 10 + "MB");
// 다시 GC 실행
System.gc();
// 최종 결과 출력
System.out.println("\n==== 메모리 증가 후 GC 실행 ====");
System.out.println("weakRef 값: " + weakRef.get()); // 이미 제거되었을 가능성 높음
System.out.println("softRef 값: " + softRef.get()); // 메모리 부족 시 제거됨
}
} catch (OutOfMemoryError e) {
System.out.println("\n💥 메모리 부족 발생! SoftReference 객체 제거 가능성 높아짐 💥");
// 다시 GC 실행
System.gc();
// 최종 결과 출력
System.out.println("\n==== 메모리 부족 후 GC 실행 ====");
System.out.println("weakRef 값: " + weakRef.get()); // 이미 제거되었을 가능성 높음
System.out.println("softRef 값: " + softRef.get()); // 메모리 부족 시 제거됨
}
}
}
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
public class ReferenceExample {
public static void main(String[] args) throws InterruptedException {
// WeakReference 생성
WeakReference<String> weakRef = new WeakReference<>(new String("WeakReference 객체 텍스트"));
// SoftReference 생성
SoftReference<String> softRef = new SoftReference<>(new String("SoftReference 객체 텍스트"));
// 참조 객체 출력
System.out.println("weakRef 값: " + weakRef.get());
System.out.println("softRef 값: " + softRef.get());
// GC 실행 요청
System.gc();
// GC 실행 후 결과 출력
System.out.println("\n==== GC 실행 후 ====");
System.out.println("weakRef 값: " + weakRef.get()); // GC가 제거 가능
System.out.println("softRef 값: " + softRef.get()); // 메모리가 충분하면 유지됨
// 💡 메모리 부족 강제 발생: 여러 개의 큰 배열을 할당하여 메모리 부족 유도
List<byte[]> memoryList = new ArrayList<>();
try {
for (int i = 0; i < 1000; i++) {
memoryList.add(new byte[10 * 1024 * 1024]); // 10MB씩 할당
System.out.println("메모리 사용 증가: " + (i + 1) * 10 + "MB");
// 다시 GC 실행
System.gc();
// 최종 결과 출력
System.out.println("\n==== 메모리 증가 후 GC 실행 ====");
System.out.println("weakRef 값: " + weakRef.get()); // 이미 제거되었을 가능성 높음
System.out.println("softRef 값: " + softRef.get()); // 메모리 부족 시 제거됨
}
} catch (OutOfMemoryError e) {
System.out.println("\n💥 메모리 부족 발생! SoftReference 객체 제거 가능성 높아짐 💥");
// 다시 GC 실행
System.gc();
// 최종 결과 출력
System.out.println("\n==== 메모리 부족 후 GC 실행 ====");
System.out.println("weakRef 값: " + weakRef.get()); // 이미 제거되었을 가능성 높음
System.out.println("softRef 값: " + softRef.get()); // 메모리 부족 시 제거됨
}
}
}
위 코드를 실행한 결과 입니다.
처음에는 WeakReference 와 SoftReference 의 각 객체에 담긴 텍스트가 잘 출력됩니다.
그러나 System.gc();를 통해 Garbage Collector(GC)가 실행된 후, 바로 WeakReference 객체가 null로 출력됩니다.
그리고 메모리 사용을 증가시켰을 때, 메모리가 부족하지 않은 경우에는 SoftReference 객체의 값이 출력됩니다.
메모리 사용량이 계속 증가하여 메모리가 부족해진 경우, SoftReference 객체가 null로 출력됩니다.