티스토리 뷰
Item08의 핵심은 자바에서 제공하는 두 가지 객체 소멸자 finalizer, cleaner를 사용하지 말라는 것이다
핵심을 충실히 따라 앞으로도 모르고 지내도록 하자
여기서 글을 끝마칠 수도 있는 내용이지만 왜인지 한번 알아보자
이제는 당연해져 버렸다 밸덩부터 읽고 시작하자
https://www.baeldung.com/java-finalize
finalizer, cleaner라는 메서드가 존재하는 게 아니라 사실 finalize(), clean() 메서드를 의미한다
C++에서는 개발자가 메모리를 직접 다루기 때문에 객체 소멸자도 중요한 의미를 갖지만 자바는 다르다
GC가 우리가 치워야 할 똥을 대신 치워주고 try-finally 문으로 명시적으로 자원을 닫아줄 수 있으며
보다 발전된 try-with-resources 문은 우리가 닫아줘야 할 자원을 알아서 닫아준다
그럼 finalizer, cleaner는 도대체 왜 등장한 걸까?
대부분의 사용 자제 API가 그렇듯 구시대의 유물이다
자원 사용 후에는 자원을 닫아주기는 해야 하고 알아서 좀 해줬으면 싶어서 나온 게 저 둘이다
문제는 finalizer는 자원 반환시킬 스레드를 지정할 수가 없고 이를 해결하기 위해
cleaner는 스레드 할당이 가능해졌지만 실행을 강제할 수 없다
말랑말랑한 귀요미 프로젝트라면 저 둘로도 충분히 굴러가겠지만 개빡센 트래픽이 들어온다면 어떻게 될까?
자원을 닫아줘야 할 객체들은 빠르게 생성되어 쌓이는데 finalizer, cleaner가 그 속도를 따라잡지 못하고
OutOfMemoryError를 시원하게 터트려준다
자원을 닫아줘야 할 객체들은 finalizer queue에 들어가는데 잠깐 운영체제와 엮어서 말해보자면
현대의 운영체제는 대부분 multi-level-feedback queue로 CPU scheduling을 수행한다
우선순위에 따라 0번 queue, 1번, 2번... 순으로 쭉 나열되고 feedback이란 CPU 할당을 받고
작업이 수행된 놈은 우선순위가 한 단계 낮아져 0번 큐에 있던 놈이 1번 큐로 내려가서 줄 다시 선다
이렇게 수행되는 이유는 우선순위를 고정시켜놓으면 우선순위가 가장 낮은 애들은 굶어 죽기 때문이고
이를 starvation이라 부른다
우선순위는 크게 kernel & user process로 나뉘는데
kernel process는 user process 보다 우선권을 갖으며 kernel 중에서도 더 중요한 놈들이 있다
그럼 finalizer queue는 어디 있을까? 쩌리 중에 쩌리다
그 말은 언제 수행될지 모르고 우선순위가 높은 프로세스들이 계속 생성된다면 얘는 굶어 죽게 되는 것이다
또한 finalizer는 심각한 보안 구멍이 있는데 생성자나 직렬화 과정에서 예외가 발생하면
생성되다만 객체에서 악의적인 하위 클래스의 finalizer가 수행될 수 있게 된다고 한다
잘 와닿지 않는 내용인데 어찌 됐든 악의적인 입력 값으로 프로그램을 헤집어 놓을 수 있다고 이해하면 된다
finalizer, cleaner를 개똥으로 생각하자, 개똥을 약으로 쓰는 경우는 두 가지가 있다
1. 명시적으로 닫아줄 필요가 있는 API에서 안전망 역할
2. Native Peer 자원 회수용
안전망 역할이란 자원 회수할 클래스에서 AutoCloseable 구현해놓으면 언젠가는 close()가 호출될 수도 있다
즉 아예 안 닫는 것보다 프로그램이 느려지더라도 닫아주는 게 좋으니 사용하는 것이다
Native Peer란 https://stackoverflow.com/questions/48260485/what-is-a-native-peer 참고하자
간단하게 보면 네이티브 메서드를 써야 되는데 직접 쓰면 의존성이 생기니 인터페이스를 두어 분리해놓은 것이다
일반적인 자바 객체가 아니므로 GC 대상에 포함되지 않으니 dispose()로 명시해 닫아주거나
언제 수행될지 모르는 finalizer, cleaner의 힘이라도 빌려야 한다
계속해서 반복되는 키워드는 명시적으로 닫아준다는 것이다
자원을 썼다면 닫아주자, 앞으로도 finalizer, cleaner는 모르는 채로 지내고
공중화장실 벽에 붙어있는 글귀처럼 지나간 자리가 아름다운 코드를 작성하도록 하자
'Java > Effective Java' 카테고리의 다른 글
[Item10] equals 일반 규약을 깨보자 (0) | 2022.02.19 |
---|---|
[Item09] 뭐든 수준 높게 사용하자 (0) | 2022.02.15 |
[Item07] 최고 JVM아 고맙다 (0) | 2022.02.12 |
[Item06] 재사용으로 성능 향상 시켜보자 (0) | 2022.02.10 |
[Item05] 때려박는 코딩은 그만, 확장성을 고려하자 (0) | 2022.02.08 |