파이널라이저의 사용을 피하자
파이널라이저(finalizer)는 예측 불가에다가 위험하기도 하며 일반적으로 불필요하다. (C++ 소멸자와 다르다.)
단점1. 신속하게 실행된다는 보장이 없다.
- 객체가 사용할 수 없게 되는 시점부터 파이널라이저가 실행되는 시점까지는 긴 시간이 소요될 수 있다.
- 파이널라이저 내부에서 실행시간이 중요한 작업을 하지 말자.
- 간혹, 파이널라이즈를 사용하면 인스턴스들의 메모리 회수와 재활용이 지연될 수 있다.
파이널라이저의 빠르기는 주로 가비지 컬렉션 알고리즘에 달려있다.
단점2. 반드시 실행 될 것인지도 보장하지 않는다.
System.gc()
와System.runFinalization()
은 파이널라이저를 실행될 가능성을 높여줄 뿐이다.- 보장하는 메소드는
System.runFinalizersOnExit()
와Runtime.runFinalizersOnExit()
이지만, 사용 금지됨
단점3. 객체의 상태가 불완전해질 수 있다.
- 예외가 무시된다.
stack trace
에서 경고조차도 출력 되지 않는다.
단점4. 성능 저하가 발생한다.
- 책에 의하면 간단한 객체 생성 및 소멸하는데 약 430배 차이가 났다.
- 그렇다면 종결 작업이 필요한 객체(ex. 파일, 스레드 등)에서 대신 무엇을 써야하나? 별도의 메소드 추가
- 가급적 종료 메소드는
try ~ fianlly
와 함께 사용하자.
파이널라이즈는 언제 사용하나?
1. 종료 메소드 호출이 누락된 객체 경우
- 일종의 ‘안정망’ 역할
- 종료 메소드 호출에 실패한 경우 -> 반드시 수정해야할 코드 결함
- 대표적인 예,
FilelnputStream , FileOutputStream, Timer , Connection
2. 네이티브 피어 객체
네이티브란? 자바 외의 다른 프로그래밍 언어(C와 C++ 같은)를 의미하며, 플랫폼에 종속적인 기계어 코드를 만드는데 이를 네이티브 피어라 한다.
네이티브 피어 객체는 자바에서 객체가 소멸되어도 가비지 콜랙터가 알지 못 하며, 재사용할 수 없다.</br> -> 파이널라이저 필요
파이널라이저는 연쇄 호출이 되지 않는다.</br>
-> 부모 클래스가 존재하는 서브 클래스에서는 try~finally를 활용하여 super.finalize()
를 실행해준다.
파이널라이저 가디언: 해당 객체를 파이널라이즈를 호출 하면서 다른 객체의 파이널라이즈도 실행하는 방법