시냅스

Java 참조 유형 과 GC (strong, soft, weak, phantom reference) 본문

Java, Spring

Java 참조 유형 과 GC (strong, soft, weak, phantom reference)

ted k 2023. 3. 26. 16:07

https://d2.naver.com/helloworld/329631

참조 유형

자바에서는 명시적으로 메모리를 해제할 수 없습니다.

그러한 일들은 GC 가 대리 수행하고 있는데요.

 

https://liltdevs.tistory.com/161

 

Java 가비지 컬렉션 Garbate Collection 정리

GC stop the world GC를 실행하기 위해 JVM이 애플리케이션의 실행을 멈춤 gc를 실행하는 쓰레드를 제외한 나머지 쓰레드는 작업을 멈춤 어떤 GC 알고리즘을 사용하더라도 꼭 발생 대개의 GC 튜닝은 이

liltdevs.tistory.com

 

어떠한 객체가 gc 의 대상이 되려면 스택 영역에서 참조하지 않아야 합니다.

gc 가 메모리를 관리를 대신해준다는 편의성과는 반대로

개발자가 메모리를 해제하고 싶을 때에도 해제할 수 없게 됩니다.

개발자는 이를 위해 아래에서 설명드릴 참조유형을 통해 관리할 수 있습니다.

 

 

참조 유형의 4단계

아래로 갈수록 참조가 약한 것으로, gc 의 대상이 되기 쉽습니다.

 

 

1. 강한 참조 Strong Reference

  1. 객체를 참조하는 일반적인 참조 유형입니다.
  2. 만약 객체가 Strong Reference 로 참조되고 있다면 해당 객체는 GC 대상이 되지 않습니다.
  3. 객체를 참조하는 모든 Strong Reference 가 해제될 때까지 객체는 메모리에 유지됩니다.
Object obj = new Object();
// 만약 GC 를 원한다면 명시적으로 null 표시를 해줘야 한다.
obj = null;

 

 

2. 약한 참조 Soft Reference

  1. Strong Reference 보다 약한 참조 유형입니다.
  2. 해당 객체를 참조는 Strong Reference 가 없고, 메모리가 부족한 경우 GC의 대상이 됩니다.
  3. java.lang.ref SoftReference class 를 사용하여 만들 수 있습니다.
  4. 참조지역성의 원리를 활용하기 위해 주로 cache 에 사용되며 Soft Reference 를 사용하여 메모리 부족 상황에서만 GC 의 대상이 되게 하여 캐시의 성능을 개선하면서 메모리 누수를 방지할 수 있게 됩니다.
Object obj = new Object();
SoftReference<Object> softRef = new SoftReference<>(obj);
obj = null;

System.gc();

// GC 가 여유롭다면 해시코드를 확인할 수 있다.
System.out.println(softRef.get());

 

 

3. 취약한 참조(…?) Weak Reference

  1. Soft Refence 보다 더 약한 참조 입니다.
  2. 해당 객체를 참조하는 Strong Reference 가 없는 경우 바로 가비지 컬렉션의 대상이 됩니다.
  3. java.lang.ref WeakReference class 로 만들 수 있습니다.
  4. 위에서 말한 캐시 관련 활용 또한 동일합니다.
  5. 다만 Weak Reference 는 GC가 여유 있어도 즉시 수거될 가능성이 높습니다.
Object obj = new Object();
WeakReference<Object> weakRef = new WeakReference<>(obj);
obj = null;

System.gc();

// 무조건 null 을 확인하게 된다.
System.out.println(weakRef.get());

 

 

4. 유령 참조 Phantom Reference

  1. 가장 약한 참조 유형입니다.
  2. 객체 수거시에도 참조가 남아있는 참조 유형입니다.
  3. 객체의 finalize() 메서드가 호출된 직후에 GC 에 의해 수거됩니다.
  4. java.lang.ref PhantomReference class 로 만들 수 있습니다.
  5. 생성자에는 넣고자 하는 클래스와 함께 ReferenceQueue 를 인자로 받습니다.
  6. PhantomReference 는 객체가 참조되지 않습니다.
  7. 객체의 finalize 메서드가 호출된 직후 Phantom Reference 가 ReferenceQueue 에 등록됩니다.
  8. 이를 통해 객체의 finalize() 메서드가 호출되었음을 알 수 있습니다.
  9. 일반적으로 Phantom Reference 는 Native 객체나 Direct Memory 와 같이 JVM 에서 관리되지 않는 자원들을 해제하기 위해 사용됩니다.
    1. Native 객체는 OS 의 메모리 영역에서 할당/관리 됩니다.
Object obj = new Object();
ReferenceQueue<Object> refQ = new ReferenceQueue<>();
PhantomReference<Object> phantom = new PhantomReference<>(obj, refQ);
obj = null;

// true
System.out.println(phantom.enqueue());
// null
System.out.println(phantom.get());

System.gc();

// false
System.out.println(phantom.enqueue());
// null
System.out.println(phantom.get());
Comments