BackEnd/Java

JAVA finalize() 소멸자 메소드에 대해

Potwings 2023. 5. 14. 21:08

주의 - finalize 메소드는 JAVA 9부터 Deprecated되었으며 사용하는 것을 지양하자

          try-finally, try-with-resources를 이용하여 처리해주자

 

글 다시 작성했습니다. 아래 글 참고해주세요

https://potwings.tistory.com/63

 

X바(자바) finalize 메소드 쓰지마세요

Java9부터는 Deprecate 되었어요 쓰지 마세요. 과거 필자는 특정 객체 동작하면서 남긴 임시 파일을 해당 객체가 소멸될 때 제거되도록 하기 위해finalize 메소드를 사용하여 처리하려 했던 적이 있었

potwings.tistory.com

 

 

finalize 메소드는 자바에서 객체가 더 이상 참조되지 않을 때 Garbage Collector가 불필요한 메모리를 회수하면서 실행하는 메소드이다.

 

finalize 메소드를 사용하지 않는 이유

1. finalize 메소드는 언제 실행될지 모른다 심지어 실행이 될 거라는 보장도 할 수 없다.
2. finalize 메소드 내부에서 발생한 exception 처리할 수 없다.

3. finalizer 공격이 가능해진다. (추후 정리 예정)

 

 

finalize 메소드는 GC가 발생할 때 실행되는 메소드일 뿐 GC의 과정이 아니다

stop-the-world는 finalize메소드가 동작할 때 발생하는 것이 아닌 GC가 동작할 때 발생한다.

 

 

삽질( 잘못된 내용)

더보기

stop-the-world에 대한 테스트

이를 확인하던 중 실제로 stop-the-world가 어떻게 작동하는지가 궁금하여 테스트해보고자 하였다.

 

 

Thread.sleep을 활용한 테스트

finalize 메소드에 thread.sleep을 활용하여 의도적으로 지연을 걸어준 뒤 stop-the-world가 발생하는지를 확인하려했다.

Person클래스에 finalize 메소드를 오버라이드
GC가 동작하도록 코드를 실행

하지만 객체가 계속적으로 생성되어도 stop-the-world는 발생하지않고 실행되었다.

심지어 finalize했다는 로깅은 잘 보이도 않는다.

계속 잘 생성되는 중...

Main메소드에 Break Point를 추가하여 디버깅을 진행해보니 이제야  finalize했다는 로깅이 어느정도 보인다.

 

 

Thread.sleep은 Thread를 TIMED_WAITING 상태로 만드는 것이기 때문에 더 정확한 테스트를 위하여 finalize 메소드에 작업을 추가하여 테스트해 보았다.

 

GC가 동작하도록 코드를 실행
finalize 메소드 수정

마찬가지로 finalize가 진행되는 중에 main 메소드가 실행되고 있다.

finalize 도중에도 main메소드가 실행되고 있다.

 

 

검색해보니 finalized 메소드는 스레드의 우선순위가 낮아서 정상적으로 실행되지 못하는 경우가 있다고 한다.

Break Point를 추가하여 Main 메소드가 잠시 중단되어 실행될 기회를 찾아서 finalize가 된 것이다.  

이를 통하여 finalize가 실행을 보장할 수 없다는 점도 직접 볼 수 있었다.

 

결론 - finalizer를 사용하는 대신 try-finally, try-with-resources를 통하여 처리해주자.