메모리누수

조현수·2023년 11월 23일
0

메모리 누수란 더이상 사용하지 않는 객체들이 힙 영역에 남아있어 불필요하게 메모리를 차지하고있는 상황을 의미한다.

자바에서는 프로그램이 돌아가는 동안 객체를 메모리에 만들어 낸다. 이 객체들은 Heap영역에 저장된다.

하지만 이 모든 객체들을 가지고 있다보면 메모리가 꽉 찰테고 자바는 이걸 해결하기 위해 GC(가비지 컬렉터)라는 청소부를 사용한다.

이 가비지 컬렉터는 더이상 사용하지 않는 객체들을 찾아서 메모리에서 없애준다.

💡 Heap 영역이란

동적으로 할당된 메모리 영역

모든 Object 타입의 데이터가 할당이 된다.
heap영역은
1. new연산을 통하여 동적으로 생성된 인스턴스객체가 저장된다. ex ) 클래스의 객체, 배열등
2. 이 객체들은 해당 객체가 소멸되기전이나 가비지콜렉터가 정리하기전까지는 이 영역에 남아있다.
3. 가비지컬랙터의 대상이되는곳

메모리 누수가 발생하는 이유는

객체에 대한 참조가 계속 유지되어 가비지 컬렉터가 해당 객체를 메모리에서 회수할수 없는 상황에서 발생한다.

가비지 컬렉터가 어떻게 사용하는 객체와 사용하지 않는 객체를 구분할까?

GC root가 그 역할을 진행한다. 힙 영역에 있는 객체중에 스택영역과 메서드 영역에 의해 참조되는 객체는 GC Root에 의해 참조되는 객체로 분류된다.

참조되지 않는 객체들은 더이상 사용되지 않는 객체라 생각하고 삭제한다.

사용하지 않는 객체임에도 불구하고 GC Root가 참조하고 있다면 가비지 컬렉터는 이 객체를 사용중인 상태로 판단하고 메모리에 유지하는데 메모리 누수의 발생원인이 된다.

메모리 누수의 종류와 예방

메모리 누수의 종류와 예방

  1. 객체 참조 누수

    public class MemoryLeakExample {
    
    	private List<T> leakList = new ArrayList<>();
    
    	public void addToLeakyList(Object obj) {
    		leakList.add(obj);
    	}
    }

    위와 같이

    import java.util.ArrayList;
    import java.util.List;
    
    public class MemoryLeakExample {
        private List<Object> leakyList = new ArrayList<>();
    
        public void addToLeakyList(Object obj) {
            leakyList.add(obj);
        }
    
        // 잘못된 방법: 리스트에서 객체를 제거하지 않음
        // 올바른 방법: 사용 후 리스트에서 객체를 제거하거나, null로 설정
        public void removeFromLeakyList(Object obj) {
            leakyList.remove(obj);
            // 또는
            // leakyList = null;
        }
    }

    로 메모리를 사용후에 객체를 꼭 지워야 메모리 누수가 발생하지 않는다.

  2. static변수 누수

    public class StaticFieldLeak {
        // static 필드로 대형 객체를 참조
        private static List<Object> staticList = new ArrayList<>();
    
        public static void addToStaticList(Object obj) {
            staticList.add(obj);
        }
    
        // 올바른 방법: 필요 없어진 후 static 필드를 null로 설정
        public static void clearStaticList() {
            staticList = null;
        }
    }
  3. 리스너와 콜백 누수

    public class EventListenerLeak {
        private EventListener listener;
    
        public void registerListener(EventListener listener) {
            this.listener = listener;
        }
    
        // 올바른 방법: 리스너를 해제하여 참조를 제거
        public void unregisterListener() {
            this.listener = null;
        }
    
        interface EventListener {
            void onEvent();
        }
    }

https://www.nextree.io/memory-leak/

profile
얼레벌레 꾸준히 하는 사람

0개의 댓글