본문 바로가기
IT 개인 공부/Java

[Java] 참조 유형(Strong, Soft, Weak, Phantom)

by Libi 2021. 7. 16.
반응형

Java는 모든 것들이 객체로 이루어져 있다고 봐도 무방하다. 또한 객체들은 new 연산을 통해 Heap 영역에 생성되기 때문에 이들은 GC(Garbage Collection) 대상이 될 수 있다.

Java에선 메모리가 부족하면 JVM의 Garbage Collector가 스택 영역과 힙 영역을 탐색하면서 스택 영역의 변수가 더 이상 참조하지 않는 힙 영역의 객체들에 대해 GC를 수행해 줌으로써 메모리를 관리한다.

하지만 개발자가 객체의 참조 강도를 약하게 만들어 GC 대상이 될 수 있도록 만들어 JVM의 메모리를 어느 정도 관리할 수도 있다.

객체의 참조 강도를 조절할 수 있는데 Java의 참조 유형은 크게 Strong, Soft, Weak, Phantom 4가지가 존재한다.

그렇다면 각 유형들에 대해 하나씩 살펴보자.

[ Strong Reference ]

Java에서 가장 기본적인 참조 유형으로 new 연산을 통해 객체를 생성하는 방법이다.

스택 영역의 strongRef 변수가 힙 영역의 객체에 대한 참조를 가지고 있는 한, strongRef 객체는 절대로 GC의 대상이 될 수 없다.

public class Main {

	static class StrongReference {
		/*
		 * StringReference 코드
		 */
	}

	public static void main(String[] args) {
		StrongReference strongRef = new StrongReference();
		System.out.println("GC 실행 전 : " + strongRef);
		System.gc();
		System.out.println("GC 실행 후 : " + strongRef);
	}
}

 

GC를 실행하였지만 strongRef는 Strong Reference이기 때문에 제거되지 않은 것을 확인할 수 있다.

만약 Strong 참조 유형의 객체를 GC의 대상이 되도록 하려면 strongRef 변수에게 Null을 할당하여 기존의 객체에 접근할 수 없는 Unreachable Object로 변경해야 한다.

strongRef = null; //strongRef의 기존 객체에 접근할 수 없도록 Unreachable Object로 변경
                  //이제 기존 객체는 GC의 대상이 될 수 있음

 

 

[ Soft Reference ]

대상 객체를 참조하는 경우가 SoftReference 객체만 존재하는 경우 GC 대상이 될 수 있다. 무조건 제거되는 것은 아니며 JVM의 메모리가 부족한 경우(Out of Memory)에만 제거된다.

import java.lang.ref.SoftReference;

public class Main {

	static class StrongReference {
		/*
		 * StringReference 코드
		 */
	}
	
	public static void main(String[] args) {
		StrongReference strongRef = new StrongReference();
		SoftReference<StrongReference> softRef = new SoftReference<>(strongRef);//strongRef 객체를 Soft 참조 유형으로 변경

		strongRef = null; //strongRef의 기존 객체에 접근할 수 없도록 Unreachable Object로 변경
		
		System.out.println("GC 실행 전 : " + softRef.get());
		System.gc();
		System.out.println("GC 실행 후 : " + softRef.get());
	}
}

 

원래는 strongRef에 Null 값을 할당하였기 때문에 GC를 수행하면 제거되어야 하지만 Soft Reference 유형이기 때문에 JVM 메모리가 넉넉하므로 Soft Reference인 softRef는 제거되지 않은 것을 확인할 수 있다.

get() 메서드는 자신이 참조하고 있는 객체를 반환하는 메서드로 여기선 StrongReference 타입인 strongRef를 반환한다. 만약 GC에 의해 제거되었다면 null을 반환한다.

 

 

[ Weak Reference ]

대상 객체를 참조하는 경우가 WeakReference 객체만 존재하는 경우 GC 대상이 되며 다음 GC 실행 시 무조건 힙 영역에서 제거된다.

import java.lang.ref.WeakReference;

public class Main {

	static class StrongReference {
		/*
		 * StringReference 코드
		 */
	}
	
	public static void main(String[] args) {
		StrongReference strongRef = new StrongReference();
		WeakReference<StrongReference> weakRef = new WeakReference<>(strongRef);//strongRef 객체를 Weak 참조 유형으로 변경
		
		strongRef = null; //strongRef의 기존 객체에 접근할 수 없도록 Unreachable Object로 변경
		
		System.out.println("GC 실행 전 : " + weakRef.get());
		System.gc();
		System.out.println("GC 실행 후 : " + weakRef.get());
	}
}

 

GC가 수행되면 JVM의 메모리에 상관없이 GC에 의해 제거된 것을 확인할 수 있다.

 

 

[ Phantom Reference ]

Phantom Reference는 가장 GC 대상이 될 확률이 높은 유형이다. Phantom Reference는 다른 Reference와 다르게 생성자에서 무조건 ReferenceQueue를 받는다.

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class Main {

	static class StrongReference {
		/*
		 * StringReference 코드
		 */
	}

	public static void main(String[] args) throws InterruptedException {
		StrongReference strongRef = new StrongReference();
		ReferenceQueue<StrongReference> refQueue = new ReferenceQueue<>();
		PhantomReference<StrongReference> phantomRef = new PhantomReference<>(strongRef, refQueue);

		System.out.println("GC 실행 전 : " + phantomRef.get());
		System.out.println(phantomRef.enqueue());
		System.gc();
		System.out.println("GC 실행 후 : " + phantomRef.get());
		System.out.println(phantomRef.enqueue());
	}
}

 

GC가 수행되기 전 finalize() 호출 후 메모리에서 정리된다고 한다. (내부적으로 ReferenceQueue에서 유지하고 있지만 GC가 수행되면 ReferenceQueue에서도 제거되는 것 같다)

또한, Phantom은 다른 참조 유형과 다르게 get() 메서드를 통해 접근하게 되면 항상 null이 반환된다. 즉, 접근을 할 수 없다는 것을 의미한다.

 

Phantom Reference는 잘 사용되지 않고, 어려운 개념이라 그냥 GC 대상이 될 확률이 가장 높은 참조 유형이라고만 알고 넘어가야겠다.

[ Reference ]

· https://lion-king.tistory.com/entry/Java-%EC%B0%B8%EC%A1%B0-%EC%9C%A0%ED%98%95-Strong-Reference-Soft-Reference-Weak-Reference-Phantom-References

· https://dev-ahn.tistory.com/117

반응형

댓글