2월 6일 -GC(Garbage Collection)

Yullgiii·2024년 2월 6일
0
post-thumbnail

Java의 가비지 컬렉션과 finalize()의 문제점

Java에서 메모리 관리는 JVM이 자동으로 해준다. 가비지 컬렉션(GC)이라는 기능을 통해 사용하지 않는 객체를 찾아내 메모리를 회수한다. 이 과정은 메모리 효율성을 높여주고, 메모리 누수를 방지하는 데 큰 역할을 한다.

가비지 컬렉션의 작동 원리

힙(Heap) 영역에 생성된 객체 중에서 더 이상 어떤 참조 변수도 가리키지 않는 객체를 가비지로 판단하고 회수한다. 이를 위해 가비지 컬렉터는 'Reachability Analysis'라는 방법을 사용해 GC Root로부터 시작하여 접근할 수 없는 객체를 찾아낸다.

finalize() 메소드와 그 문제점

객체가 가비지로 판단되어 회수되기 직전에 finalize() 메소드가 호출된다. 여기서 리소스 해제 같은 정리 작업을 할 수 있지만, 여러 문제가 있다.

  • 성능 저하: finalize()가 호출되어야 하는 객체는 회수 과정이 더 복잡해져 성능이 저하될 수 있다.
  • 불확실성: finalize()의 호출 시점을 예측하기 어렵다.
  • 메모리 누수 가능성: finalize() 내에서 객체가 다시 참조되면, 가비지로 판단되지 않게 된다.

null 할당과 가비지 컬렉션

변수를 null로 설정하면, 해당 변수가 참조하던 객체는 더 이상 참조되지 않는 상태가 된다. 이 상태가 되면 객체는 가비지 컬렉션의 대상이 될 수 있다. 하지만 이는 가비지 컬렉터가 실행되는 시점에 따라 다르다.

예제

public class GarbageCollectionExample {
    public static void main(String[] args) {
        MyClass obj = new MyClass("Test");
        obj = null; // obj가 참조하던 MyClass 인스턴스를 가비지 컬렉션의 대상으로 만든다.

        // 가비지 컬렉터 호출 요청 (실제 호출 시점은 JVM이 결정)
        System.gc();

        // 대기 시간 추가 (finalize() 호출 확인용)
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    private static class MyClass {
        private String name;

        public MyClass(String name) {
            this.name = name;
        }

        @Override
        protected void finalize() {
            System.out.println(name + " 객체의 finalize()가 실행됨");
        }
    }
}

이 예제에서 MyClass 인스턴스를 생성하고, null을 할당해서 가비지 컬렉션 대상으로 만든다. System.gc()를 호출해 가비지 컬렉터를 요청하지만, 실제 가비지 컬렉션이 일어나는 시점은 JVM이 결정한다. finalize() 메소드에서는 간단한 메시지를 출력해 호출 여부를 확인할 수 있다.

이 예제와 설명을 통해 Java의 가비지 컬렉션과 finalize() 메소드의 사용 시 주의해야 할 점들을 잘 이해할 수 있다. finalize() 대신 자바 7부터 제공하는 try-with-resources를 사용하는 것이 좋다. 이를 통해 리소스를 보다 안전하고 효율적으로 관리할 수 있다.

가비지 컬렉터 유형

Java는 다양한 가비지 컬렉터를 제공하며, 각각의 가비지 컬렉터는 특정 유형의 애플리케이션에 더 적합할 수 있다.

  • Serial Garbage Collector: 단일 스레드를 사용하여 가비지 컬렉션을 수행한다. 소규모 데이터에 적합하며, 작업을 수행하는 동안 애플리케이션의 모든 작업을 멈춘다(Stop-The-World).
  • Parallel Garbage Collector: 여러 스레드를 사용해 가비지 컬렉션을 병렬로 수행한다. 멀티프로세서 환경에서 성능을 향상시키는 데 적합하다.
  • Concurrent Mark Sweep (CMS) Garbage Collector: 애플리케이션의 중단 시간을 최소화하기 위해 설계되었다. 가비지 컬렉션 과정의 대부분을 애플리케이션 스레드와 동시에 수행한다.
  • G1 Garbage Collector: 큰 힙을 관리하기 위해 설계되었으며, 가비지 컬렉션의 중단 시간을 예측 가능하게 유지하려고 한다.

가비지 컬렉션 최적화 전략

  • 객체 할당 최소화: 필요하지 않은 객체 생성을 피하며, 가능한 한 기존 객체를 재사용한다.
  • 대형 객체 주의: 큰 객체는 가비지 컬렉션 시간에 영향을 미칠 수 있으므로, 크기가 큰 객체의 생성과 할당은 신중하게 고려해야 한다.
  • 가비지 컬렉터 선택: 애플리케이션의 요구 사항과 작업 부하에 가장 적합한 가비지 컬렉터를 선택한다.
  • JVM 옵션 조정: -Xms와 -Xmx 같은 JVM 옵션을 조정하여 힙의 초기 크기와 최대 크기를 설정할 수 있다. 적절한 힙 크기 설정은 성능에 큰 영향을 미칠 수 있다
profile
개발이란 무엇인가..를 공부하는 거북이의 성장일기 🐢

0개의 댓글