[JVM] 자바 가상 머신, 강제종료 원인 2가지 (데몬스레드, finalize)

[JVM] 자바 가상 머신, 강제종료 해결 2가지 (데몬스레드, finalize)


데몬 스레드


애플리케이션을 작성하다 보면 스레드를 하나 만들어 부수적인 기능을 처리하도록 하고는 싶지만, 그렇다고 해서 해당 스레드가 떠 있다는 이유로 JVM이 종료되지 않게 하고 싶지는 않을 경우가 있다.


이럴 때 사용할 수 있는 것이 바로 데몬daemon 스레드이다. 스레드는 두 가지 종류로 나눠볼 수 있는데, 하나는 일반 스레드이고 다른 하나는 데몬 스레드이다. 자바 가상 머신 JVM이 처음 시작할 때 main 스레드를 제외하고 자바 가상 머신 JVM 내부적으로 사용하기 위해 실행하는 스레드(가비지 컬렉터 스레드나 기타 여러 가지 부수적인 스레드)는 모두 데몬 스레드이다.


새로운 스레드가 생성되면 자신을 생성해 준 부모 스레드의 데몬 설정 상태를 확인해 그 값을 그대로 사용하며, 따라서 main 스레드에서 생성한 모든 스레드는 기본적으로 데몬 스레드가 아닌 일반 스레드이다.

일반 스레드와 데몬 스레드는 종료될 때 처리 방법이 약간 다를 뿐 그 외에는 모든 것이 완전히 같다. 스레드 하나가 종료되면 자바 가상 머신 JVM은 남아있는 모든 스레드 가운데 일반 스레드가 있는지를 확인하고, 일반 스레드는 모두 종료되고 남아있는 스레드가 모두 데몬 스레드라면 즉시 JVM 종료 절차를 진행한다.


JVM이 중단(halt) 될 때는 모든 데몬 스레드가 버려지는 셈이다.

finally 블록의 코드도 실행되지 않으며, 호출 스택도 원상 복구되지 않는다.


이런 특성이 있기 때문에 데몬 스레드는 보통 부수적인 용도로 사용하는 경우가 많다. 데몬 스레드에 사용했던 자원을 꼭 정리해야 하는 일을 시킨다면, 자바 가상 머신 JVM이 종료될 때 자원을 정리하지 못할 수 있으므로 적절하지 않다.


예를 들어 I/O와 관련된 기능을 데몬 스레드에 맡기는 것은 그다지 좋은 방법이 아니다.


다시 말하지만 데몬 스레드는 예를 들어 메모리 내부에 관리하는 캐시에서 기한이 만료된 항목을 주기적으로 제거하는 등의 부수적인 단순 작업을 맡기기에 적절한 스레드이다.


데몬 스레드는 예고 없이 종료될 수 있으므로 애플리케이션 내부에서 시작시키고 종료시키며 사용하기에는 그다지 좋은 방법이 아니다.


JVM 자바가상머신 강제종료 GC[[JVM] 자바 가상 머신, 강제종료 원인 2가지 (데몬스레드, finalize)]


finalize 메소드

애플리케이션 내부에서 더는 사용하지 않는 객체가 있다면 대부분 가비지 컬렉터가 알아서 수집해 제거하고 메모리를 확보하는 일을 잘 수행해준다.


하지만 파일이나 소켓과 같은 일부 자원은 더는 사용하지 않을 때 운영체제에게 되돌려 주려면 반드시 자원을 명시적으로 정리해야 한다. 가비지 컬렉터는 finalize 메소드에 기능이 추가된 객체를 좀 더 특별한 방법으로 처리해 이런 과정이 효과적으로 움직이도록 하고 있다.


finalize 메소드가 정의되어 있는 객체는 명시적으로 풀어줘야 하는 자원을 정리할 수 있도록 가비지 컬렉터에 수집될 때 finalize 메소드를 호출해 실행시킨다.


JVM 자바가상머신 종료[[JVM] 자바 가상 머신, 강제종료 원인 2가지 (데몬스레드, finalize)]


finalize 메소드는 자바 가상 머신 JVM이 관리하는 스레드에서 직접 호출하기 때문에 finalize 메소드에서 사용하는 모든 애플리케이션 상태 변수를 다른 스레드에서도 얼마든지 동시에 사용할 수 있으며, 따라서 동기화 작업이 필수이다.


하지만 finalize 메소드는 과연 실행될 것인지 그리고 언제 실행될지에 대해서 아무런 보장이 없고, finalize 메소드를 정의한 클래스를 처리하는 데 상당한 성능상의 문제점이 생길 수 있다. 게다가 finalize 메소드를 올바른 방법으로 구현하기도 쉬운 일이 아니다.


대부분은 finalize 메소드를 사용하는 대신 try-finalize 구문에서 각종 close 메소드를 적절하게 호출하는 것만으로도 finalize 메소드에서 해야 할 일을 훨씬 잘 처리할 수 있다.


finalize 메소드가 더 나을 수 있는 유일한 예는 바로 네이티브 메소드에서 확보했던 자원을 사용하는 객체 정도밖에 없다.


여기에서 언급한 이런저런 이유를 생각하고 보면 웬만해서는 finalize 메소드를 사용하지 말고 다른 방법으로 처리하며, finalize 메소드를 사용하게 되어 있는 클래스도 멀리하는 편이 좋겠다(자바 플랫폼 라이브러리에 포함된 클래스는 예외이다).


출처 - 자바 병렬 프로그래밍, 강철구, 245p~249p

[JVM] 자바 가상 머신, 강제종료 원인 2가지 (데몬스레드, finalize)

댓글(0)

Designed by JB FACTORY