소멸자
생성자가 리소스를 메모리에 할당하기 위해 존재한다면, 소멸자는 사용되지 않는 리소스를 회수해 메모리를 확보하기 위해 존재
C, C++과 같은 언어에서는 리소스가 알아서 회수되지 않기 때문에 소멸자(destructor)가 존재하는 것이 보편적
그러나 Java는 가비지 컬렉터가 알아서 참조되지 않는 리소스를 회수하기 때문에, 소멸자를 통해 객체를 회수하는 것은 위험
Java에서 명시적으로 소멸자를 호출하는 것의 위험
Java에는 2개의 소멸자 finalizer, cleaner가 존재
소멸자의 정확한 실행 시점을 예측할 수 없음 (GC 구현 로직에 따라 다름)
소멸자가 반드시 실행된다고 보장할 수 없음
GC의 효율을 저하시켜 프로그램 성능 저하를 유발
Java에서 리소스를 명시적으로 회수하려면?
파일, 스레드와 같이 명시적으로 종료해야 할 리소스를 포함한 객체의 경우
AutoCloseable, try-with-resource
AutoCloseable
인터페이스를 상속한 뒤 close 메서드를 오버라이딩해 이 메서드 내에서 해당 객체가 회수될 때 수행되어야 할 동작들을 정의이 close 메서드는 외부에서
try-with-resource
를 통해 해당 객체를 생성함이 보장된다면 반드시 호출됨
클라이언트에서 잘못된 호출을 하는 경우
위의 경우 main 메서드가 처리되지 않은 예외에 의해 비정상적 종료되고 있음
실행 결과 close() 메서드 내 로그가 찍히지 않음을 확인할 수 있음
즉, item8 객체가 정상적으로 소멸되지 않고 프로그램이 종료됨
클라이언트에서 올바르게 호출하는 경우
위와 같이 try-with-resource를 통해 item 객체를 생성하는 경우, 프로그램이 비정상적으로 종료됨에도 close 메서드가 호출됨을 확인할 수 있음
클라이언트가 올바르게 사용하지 못한다면?
이러한 경우를 대비하여 cleaner를 이용해 명시적으로 회수하도록 구현할 수 있음
하지만 이는 단순히 안전망으로만 사용하고, 클라이언트가 try-with-resource를 사용하도록 하는 것이 가장 좋은 구현법
AutoCloseable을 안전하게 구현하는 방법
외부에서 close에 의해
닫힌
자원을 사용하기 위해 호출하는 실수를 할 수도 있음이 경우 해당 자원의 사용을 막기 위해 AutoCloseable을 구현한 클래스에서는 close 여부를 boolean 필드 값 등으로 관리하는 것이 좋음
예시: isClosed 라는 필드를 소유하고, close 메소드의 끝단에서 이를 true로 설정 (다른 메서드들은 동작 전 isClosed가 false인지 확인)
Last updated