상세 컨텐츠

본문 제목

객체 참조 해제, Java 참조 유형

java

by nownow 2025. 3. 6. 17:12

본문

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    public StackO {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }
    public Object pop() {
        if (size = 0)
            throw new EmptyStackException();
        return elements[—size];
    }

    /**
     * 원소를 위한 공간을 적어도 하나 이상 확보한다.
     *  배열 크기를 늘려야 할 때마다 대략 두 배씩 늘린다.
    */
    private void ensureCapacity() {
    if (elements.length = size)
        elements = Arrays.copyOf(elementsf 2 * size + 1);
    }
 }

GC를 통해 메모리 관리가 이루어지는 Java에서는 참조되지 않는 객체의 메모리 할당을 JVM에서 해제해준다.

일반적인 경우에는 최소한의 참조가 되도록 구현하고 참조하고 있는 변수가 scope에서 벗어나며 자동으로 해제된다.

 

하지만 위와 같이 객체 배열을 가지고 있는 클래스 즉 자기 메모리를 직접 관리하는 클래스에서

pop() 메서드를 수행할 때 객체 배열에 처리를 해주지 않고

size 필드 연산만 해준다면, Object 참조 배열에서 삭제되어야 할 객체를 그대로 참조하고 있어 메모리 누수가 발생한다.

 

이런 상황을 방지하기 위해 elements[size] = null 과 같은 처리가 필요하다.

 

 

특정상황을 위해 참조 유형을 고려할 수도 잇다.

Java의 참조 유형에는 4가지가 있다.

1.Strong Reference

2.Soft Reference

3.Weak Reference

4.Phantom Reference

아래로 갈 수록 GC의 대상이 될 시점이 빠르다.

 

Strong Reference

일반적으로 사용하는 new 키워드 인스턴스 생성의 경우가 Strong Reference다.

TestClass strongRef = new TestClass();

 

Soft Reference

강한 참조를 하고 있는 변수가 사라지더라도 Soft Reference를 유지하고 있는 상태 일때는

JVM의 메모리가 부족해지는 시점에 GC의 대상이 된다.

 

Weak Reference

강한 참조를 하고 있는 변수가 사라지면 Weak Reference가 참조를 유지하고 있더라도

GC의 대상이 된다.

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Stack {
    public static void main(String[] args) {
        TestClass strongRef = new TestClass();
        TestClass strongRef2 = new TestClass();
        SoftReference<TestClass> softRef = new SoftReference<>(strongRef);
        WeakReference<TestClass> weakRef = new WeakReference<>(strongRef2);
        strongRef2=null;
        strongRef=null;
        System.out.println(softRef.get());
        System.out.println(weakRef.get());
        System.gc();
        System.out.println(softRef.get());
        System.out.println(weakRef.get());
    }
}

 

Weak Reference 방식의 HashMap이 존재한다.

public static void main(String[] args) {
        Object test1 = new Object();
        Object test2 = new Object();
        WeakHashMap<Object, String> weakHashMap = new WeakHashMap<>();
        weakHashMap.put(test1,"Test1");
        weakHashMap.put(test2,"Test2");
        for(String str : weakHashMap.values()){
            System.out.println(str);
        }
        test1=null;
        test2=null;
        System.gc();
        for(String str : weakHashMap.values()){
            System.out.println(str);
        }
    }

필요한 값을 캐싱하는 용도로 HashMap을 사용할 때 외부에서 키 객체를 참조하는 동안만 캐싱을 유지하도록

구현할 수 있다.

 

 

세번째로 콜백 구현 시에도 메모리 누수가 발생할 수 있다.

public class Caller {
    public static void main(String[] args) {
        Callee callee = new Callee();
        Callback callback = () -> {
            System.out.println("콜백");
        };
        callee.setCallback(callback);
        callee.task();
    }
}
@FunctionalInterface
public interface Callback {
    public void callbackMethod();
}
public class Callee {
    Callback callback;
    public void setCallback(Callback callback){
        this.callback=callback;
    }
    public void task(){
        System.out.println("작업 완료");
        callback.callbackMethod();
    }
}

위와같이 일반적인 콜백 구현에서는 Callee가 callback을 강한 참조로 갖고 있기 때문에

Caller 객체가 사라지더라도 callback 객체가 사라지지 않는다.

import java.lang.ref.WeakReference;

public class Callee {
    WeakReference<Callback> callback;

    public void setCallback(Callback callback){
         this.callback = new WeakReference<>(callback);
    }
    public void task(){
        System.out.println("작업 완료");
        Callback callbackGet = callback.get();
        callbackGet.callbackMethod();
    }
}

콜백을 약한참조로 지정함으로서 보완할 수 있다.

WeakReference<>() 에서 실제 내부 객체를 꺼내서 사용해야 메서드를 호출할 수 있기에 .get()을 사용한다.

'java' 카테고리의 다른 글

Comparable  (0) 2025.03.12
클래스 빌더 패턴  (2) 2025.03.04
enum 매핑  (0) 2025.02.28
자바 클래스 정렬 기준 설정. PriorityQueue, sort. Comporable, Comporator (코테준비)  (0) 2024.10.20
Object Class, 불변객체, String  (0) 2024.03.30

관련글 더보기