finalize()
입니다. 해당 메서드는 Object
에 있는 메서드이며, 객체가 소멸할 때(GC에 회수될 때) 실행되는 메서드로 다른 클래스들의 경우 Object
에 존재하는 finalize()
메서드를 Overriding
하여 사용합니다.Cleaner
입니다. Cleaner는 객체(클래스) 이며, 자신을 실행할 스레드를 받거나, 직접 생성하여 객체 소멸을 진행하는 객체입니다.<aside> 💡 주의할 점
Java에서의 객체 소멸자와 C++에서의 객체 소멸자는 다른 개념입니다.
C++에서의 소멸자는 new로 할당된 자원들을 회수하는 보편적인 방법으로서 사용되나 Java 에서의 객체 소멸자는 객체가 소멸될 때 특정 연산과 같은 행동(behavior)을 정의하는데 사용됩니다.
C++에서의 소멸자와 같은 개념은 Java에서 GC를 떠올리면 되겠습니다.
</aside>
finalize()
메서드와 Cleaner 객체는 매우 많은 문제점을 가지고 있습니다. 그 중 finalize()
의 경우, JDK 1.9부터 사용을 자제(deprecated)해야 하는 메서드로 되어 있습니다.
Object.finalize()
가 등록되어 있으며 AutoCloseable
인터페이스를 구현하거나, Cleaner
객체를 사용하는 것을 권장한다고 적혀 있습니다.해당 파트에서는 이 두 소멸자가 왜 문제가 되는지에 대해 알아보겠습니다.
finlizer
와 cleaner
는 호출되어도 해당 메서드가 즉시 수행된다는 보장이 없습니다.
즉 호출이 이미 되어도 실행이 언제 되는지는 알 수 없습니다. 호출된 즉시 실행될 수도 있고, 호출된 뒤 프로그램이 종료될 때 까지 실행되지 않을 수도 있습니다.
이는 finalizer
나 cleaner
로 제때 실행되어야 하는 작업을 할 수 없다는 것을 의미합니다. 언제 실행되는지에 대한 것이 JVM의 GC에 의존하기 때문입니다.
또한 finlizer나 cleaner의 실행 시점에 의존적인 프로그램의 동작도 문제를 일으킬 수 있습니다. 이유는 동일하게 언제 실행되는지 알 수 없기 때문입니다.
<aside> 💡 Connection Pool 이란?
Connection Pool은 DB Connection 객체를 일정 수 보관하고 있는 저장소와 같은 개념입니다.
Spring과 같은 멀티스레드 환경의 경우, 여러 개의 Connection 객체가 필요할 수 있는데 Connection 객체는 꽤 무거운 객체에 속합니다.
이를 계속 새롭게 생성하고 폐기하는것이 비효율적이므로, 프로그램 시작 시 일정 수의 Connection 객체를 미리 만들어 저장해놓음으로서 여러 개의 Connection 객체가 필요한 상황이 오더라도 대기 시간을 최소화할 수 있습니다.
</aside>
finalizer
에 의한 OutOfMemoryError
가 있습니다. 실제로 finalizer
와 cleaner
가 수행되는 스레드는 다른 스레드에 비해 우선순위가 낮습니다.
finalizer
와 cleaner
가 일반적인 스레드를 사용하는것이 아닌 데몬 스레드(Daemon Thread)를 사용하여 수행되기 때문입니다.