본문 바로가기
프로그래밍 놀이터/디자인 패턴, 리펙토링

[Effective Java] 쓸모 없는 객체 참조를 제거하자.

by 돼지왕 왕돼지 2016. 1. 4.
반응형

 [Effective Java] 쓸모 없는 객체 참조를 제거하자.


Posted by 돼지왕왕돼지 API, C, C++, cache, Callback, Effective JAVA, garbage collection, GC, gc 원리, gc 증가, heap profiler, Java, LinkedHashMap, Listener, memory leak, NPE, NullPointerException, OOM, OutOfMemoryError, removeeldestentry, scope 최소화, Tool, weak reference, weakhashmap, [Effective Java] 쓸모 없는 객체 참조를 제거하자., 가비지 컬렉션, 가장 좋은 방법, 가치, 간단, 극단, 누적, 도구, 도움, 등록, 디스크 페이징, 리스너, 릭 요소, 말소, 메모리 관리, 메모리 누수, 메모리 누출, 메모리 릭, 메모리 할당, 메모리 할당 회수 횟수, 메모리 회수, 백그라운드 스레드, 성능 저하, 쓸모 없는 객체 참조, 쓸모 없는 객체 참조를 제거하자., 쓸모 없는 참조, 언어, 에러, 의도, 이해, 자동, 자바, 장점, 정확히 이해, 제거, 캐시, 콜백, 힙 프로파일러


-
자바와 같이 가비지 컬렉션을 자동으로 해주는 언어는 메모리 관리를 따로 해줄 필요가 없다고 생각하기 쉬우나, 이는 틀린 생각이다.
GC 의 원리에 대해 정확히 이해하고 메모리 관리를 해주어야 한다.
다만 그 메모리 관리하는 범위가 C, C++ 과 같은 GC 가 없는 언어들에 비해 더 간단할 뿐!


-
자바에서도 메모리 누출(memory leak)이 쉽게 발견된다.
메모리 누수가 생기면, 성능저하의 형태로 서서히 나타난다.
GC 작업이 증가하거나, 메모리 할당과 회수 횟수가 빈번해지기 때문이다.
심하면 디스크 페이징 현상이 나타나기도 하고, 아주 극단적으로는 OutOfMemoryError 가 발생한다.

메모리 누수의 무서운 점은, 특정 객체 참조가 의도하지 않게 계속 유지되면, 이에 엮인 다른 객체들도 GC 대상에서 제외된다.
그럼 단 몇개의 참조만 의도하지 않게 유지되어도 OutOfMemoryError 까지 이어질 수 있다.


-
쓸모 없는 참조란 객체에 대한 참조 값을 갖고 있지만 다시는 사용되지 않을 참조를 말한다.


-
이런 부류의 문제에 대한 해결책은 간단하다.
쓸모 없는 참조를 null 로 만드는 것이다.


-
쓸모 없는 참조를 null 로 만들면 부수적인 장점이 생긴다.
실수로 사용되면 NullPointerException 이 생겨 프로그램 실행이 중단되고,
이로서 엉뚱하게 실행되어 이상한 상태로 꼬여 에러를 잡기 힘든 상태보다 훨씬 유리하다.


-
메모리 누수로 고통을 겪어 본 프로그래머들은 코드 실행이 끝나는 즉시 너무 지나치게 모든 객체 참조를 null 로 만드는 경향이 있다.
이것은 필수적인 것도 아니고, 바람직하지도 않다.
객체 참조를 null 로 바꾸는 것은 꼭 필요할 때만 예외적으로 행해야 한다.


-
쓸모 없는 객체 참조를 제거하는 가장 좋은 방법은 객체 참조의 scope 를 작게 유지하는 것이다.


-
메모리 누출이 흔히 생기는 또 다른 근원은 캐시(cache) 이다.
객체 참조를 캐시에 저장하면 저장했다는 것을 잊어 버리고 객체가 더 이상 필요 없을 떄까지 캐시에 내버려 두기 쉽다.
이에 대한 해결책은 여러 가지가 있다.


해결책 1
    캐시 외부에 캐시의 키에 대한 참조가 있을 동안만 캐시에 저장된 항목이 유효한 그런 캐시는 WeakHashMap 으로 사용 가능하다.


해결책 2
    캐시는 생명주기가 잘 정의되지 않아 시간이 경과하면거 가치가 없게 된 항목들이 발생하는데 백그라운드 스레드로 처리하거나 새 항목을 캐시에 추가할 때 같이 처리하는 것이 좋다.
    LinkedHashMap 클래스에서 자신의 removeEldestEntry 메소드를 사용해서 새로운 항목을 캐시에 추가할 때 오래된 캐시항목을 제거해준다.


-
메모리 누출의 세 번째 근원은 리스너(listener)와 콜백(callback) 이다.클라이언트가 콜백을 등록하되 말소는 하지 않는 API 를 구현하면, 우리가 뭔가 조치를 취하지 않는 한 콜백은 계속 누적된다.

콜백이 신속하게 가비지 컬렉션 되도록 하는 가장 좋은 방법은 약한 참조(weak reference)만을 저장 유지하는 것이다.
예를 들어 WeakHashMap 의 키로 콜백을 저장한다.


-
메모리 누출은 처음부터 그와 같은 문제가 생기지 않도록 막는 방법이 최선이며,
만약 문제가 생긴다면 힙 프로파일러(heap profiler)와 같은 도구로의 도움을 받아 릭 요소를 찾아 제거해야 한다.






반응형

댓글