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)를 사용하여 수행되기 때문입니다.