메모리 관리
- 안드로이드 디바이스는 제한된 메모리 자원을 가지고 있기 때문에 *메모리 누수가 발생하면 앱의 성능이 저하되고, 심각한 경우 앱이 강제 종료될 수 있기 때문에 메모리 관리는 중요하다.
- 메모리 누수(Memory Leak) : 프로그램이 동적으로 할당한 메모리 영역 중 일부를 더 이상 사용하지 않음에도 불구하고 해제하지 않아, 사용할 수 있는 메모리가 점점 줄어드는 현상
- 앱이 종료될 때 참조하고 있는 객체가 남아있어 메모리 누수가 발생할 수 있기 때문에, 애플리케이션 컨텍스트를 멤버 변수로 사용하지 않는 것이 좋다.
- Weak Reference 는 객체가 더 이상 사용되지 않을 때 GC 가 해당 객체를 수거할 수 있기 때문에, Weak Reference 를 적절히 활용하는 것이 중요하다.
- GC(Carbase Collection) : JVM(자바 가상 머신)의 Heap 영역에서 동적으로 할당됐던 메모리 중 필요 없게 된 메모리 객체(garbage)를 모아 주기적으로 제거하는 프로세스
- GC 는 사용되지 않는 객체를 수거하여 메모리를 해제하는 역할을 하기 때문에, GC 의 동작 원리를 이해하고, 메모리 누수를 방지하기 위한 추가적인 방법을 고려하는 것이 중요하다.
- GC 는 *Reference 의 강약에 따라 Reachable 객체를 제외하고 모두 쓰레기로 간주한다.
- Reference : Strong < Soft < Weak < Phantom Reference 로 분류되며, 이를 통해 GC 에 의해 제거될 데이터에 우선순위를 적용하여 효율적인 메모리 관리를 할 수 있다.
Strong Reference
- 흔히 객체를 생성하게되면 생기는 참조 형태
- 객체를 강하게 참조하는 Strong Reference 는 객체가 더 이상 사용되지 않더라도 GC 가 해당 객체를 수거하지 않는다.
- 예시: 사용자가 자신의 이미지를 이용해 웹사이트를 디자인할 수 있는 애플리케이션
- 디스크에서 이미지를 로드하는 데 많은 비용이 들고, 거대한 이미지가 동시에 메모리에 두 개 이상 존재하는 상황을 피하기 위해 애플리케이션에서는 이미지를 *캐시하는 것이 필수적이다.
- 캐시(Cache) : 자주 사용하는 데이터나 값을 미리 복사해 놓는 임시 장소
- 이미지 캐시는 필요하지 않을 때 이미지를 다시 로드하지 않도록 설계되어 있으며, 이는 캐시가 메모리에 있는 모든 이미지에 대한 참조를 항상 포함해야함을 의미한다.
- 문제점: 강한 참조의 경우, 그 참조 자체가 이미지를 메모리에 계속 유지하도록 강제한다.
- 해결책: 이미지가 더 이상 메모리에 필요하지 않은 시점을 판단하고, 이를 기반으로 캐시에서 제거하여 가비지 수집의 대상이 되도록 해야한다.
- 결국, 개발자는 가비지 수집기의 역할을 모방하여 객체가 메모리에 남아 있어야 하는지를 수동으로 판단해야 하는 상황이 반복적으로 발생하게 된다.
- 디스크에서 이미지를 로드하는 데 많은 비용이 들고, 거대한 이미지가 동시에 메모리에 두 개 이상 존재하는 상황을 피하기 위해 애플리케이션에서는 이미지를 *캐시하는 것이 필수적이다.
Soft Reference
- GC 에 의해 객체가 수거될 수도 있지만, 메모리에 충분한 여유가 있을 경우, GC 가 실행되고 있더라도 객체가 수거되지 않는다.
- 메모리가 적은 모바일 기기 특성상 Weak Reference 와 동작하는 게 크게 다르지 않다.
Weak Reference
- 객체를 약하게 참조하는 Weak Reference 는 객체가 더 이상 사용되지 않을 때 GC 가 해당 객체를 수거할 수 있도록 한다.
- Weak Reference 의 생성자에 *ReferenceQueue 를 전달하면, 참조된 객체가 GC 대상이 될 때 자동으로 ReferenceQueue 에 enqueue(삽입)된다. 이후 일정한 간격으로 ReferenceQueue 를 처리하여 소멸된 참조에 대한 필요한 정리 작업을 수행할 수 있다.
- ReferenceQueue : 객체가 더 이상 필요하지 않아서 GC 에 의해 메모리에서 제거될 때, 참조 객체가 '소멸'되었음을 알리는 참조 대기열
- 즉, ReferenceQueue 클래스를 사용하면 소멸된 참조를 쉽게 추적할 수 있다.
- ReferenceQueue : 객체가 더 이상 필요하지 않아서 GC 에 의해 메모리에서 제거될 때, 참조 객체가 '소멸'되었음을 알리는 참조 대기열
- 객체가 weakly reachable 이라고 판단될 때 enqueue 된다. (아직 *finalize() 와 GC 가 일어나지 않은 상태)
- finalize()
- GC 가 언제 객체를 제거할지 알고 싶거나 특정 작업을 수행해야 할 때 finalizer 를 사용한다.
- GC 가 특정 객체에 대해 unreachable 이라고 판단하게 되면 객체 내에서 finalize() 메서드가 있는지를 확인한다.
- finalize() 메서드가 없다면, GC 는 객체를 메모리에서 제거한다.
- finalize() 메서드가 있다면, GC 는 메모리에서 객체를 제거하기 전에 두 번 확인하여 해당 객체가 여전히 unreachable 상태인지 판단한 후, 그때 객체를 메모리에서 제거한다.
- finalize() 메서드가 실행되는 동안, 해당 객체가 다시 reachable 상태가 될 수 있기 때문이다. 예를 들어, finalize() 메서드 내에서 해당 객체를 다른 곳에서 참조하게 만들면 객체가 다시 살아난다.
- finalize()
Phantom Referece
- 메모리에서 Phantom Reference 의 참조값이 제거된 후에만 ReferenceQueue 에 enqueue 되기 때문에, get() 메서드는 항상 null 이 반환되고, finalize() 가 호출되지 않기 때문에 객체가 다시 살아나는 문제를 피할 수 있다.
- finalize() 는 어느 시점에 호출되는지, 메모리에서 언제 해제되는지 정확히 알 수 없기 때문에 Phantom Reference 를 사용하는 것이 훨씬 더 안전하고 효율적이다.
- 명확하게 메모리에서 제거되었는지 확인이 필요한 경우에 사용한다.
- 객체가 제거된 후 처리할 로직을 수행할 때, finalize() 메서드보다 더 정밀한 후처리가 가능하다.
- 이후 Phantom Reference 에서 clear() 메서드를 직접 수행한다.
안드로이드 메모리 관리와 위크 레퍼런스의 중요성
이 블로그 포스트는 안드로이드 개발에서 메모리 관리의 중요성과 위크 레퍼런스의 활용 방법에 대해 다룹니다. 메모리 누수를 방지하고 앱의 안정성을 높이기 위한 다양한 방법을 소개합니다.
f-lab.kr
[Kotlin] Weak Reference - 동식이 블로그
[Kotlin] Weak Reference
dongsik93.github.io
[Kotlin] Weak Reference
weak Reference 란 무엇일까요?
medium.com
'안드로이드 > Android' 카테고리의 다른 글
[Android] 직렬화(Serialization, Parcelable), 역직렬화(Deserialization) (0) | 2024.10.27 |
---|---|
[Android] View (0) | 2024.10.05 |
[Android] ConstraintLayout (0) | 2024.10.02 |