0Pricing
Java Academy · 강의

메모리 누수 감지와 수정

일반적인 메모리 누수 패턴(정적 컬렉션, 리스너, 캐시)을 식별하고 수정합니다.

메모리 누수 감지와 수정은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

Java의 메모리 누수란 무엇입니까

Java 메모리 누수는 더 이상 필요하지 않은 객체가 강하게 도달 가능한 상태로 남아 가비지 컬렉션이 회수하지 못할 때 발생합니다. OutOfMemoryError가 발생할 때까지 힙이 증가합니다.

정적 컬렉션 누적

계속 증가하는 컬렉션을 보유한 정적 필드는 전형적인 누수 원인입니다. 추가되었지만 제거되지 않은 객체는 애플리케이션의 수명 동안 계속 살아 있습니다.

public class Cache {
    // LEAK: static list grows forever if items are never removed
    private static final List<Object> items = new ArrayList<>();
    public static void add(Object o) { items.add(o); }
    // Fix: add a remove() method or use a bounded cache
}

등록 해제되지 않은 이벤트 리스너

리스너를 등록한 뒤 제거하지 않으면 리스너와 리스너가 참조하는 모든 객체가 계속 살아 있게 됩니다. 더 이상 필요하지 않은 리스너는 항상 등록 해제하십시오.

// Leak:
sensor.addListener(new DataLogger());
// Fix:
DataLogger logger = new DataLogger();
sensor.addListener(logger);
// ... when done:
sensor.removeListener(logger);

정리되지 않은 ThreadLocal 변수

스레드 풀에서는 스레드가 재사용되므로 ThreadLocal 값이 작업 사이에도 남아 있습니다. 값을 정리하지 않으면 한 작업의 데이터가 같은 스레드에서 실행되는 이후 작업으로 유출됩니다.

private static final ThreadLocal<MyContext> CTX = new ThreadLocal<>();
// Always clean up after each task:
try {
    CTX.set(new MyContext(requestId));
    doWork();
} finally {
    CTX.remove(); // prevents leak in pooled threads
}

핫 배포 애플리케이션의 클래스 로더 누수

서블릿 컨테이너에서는 배포할 때마다 새 클래스 로더가 사용됩니다. 이전 클래스 로더의 클래스를 정적 참조로 보유하는 클래스가 하나라도 있으면 이전 클래스 로더 전체와 그 안의 모든 클래스를 가비지 컬렉션할 수 없습니다.

힙 덤프로 누수 감지

jmap -dump:format=b,file=heap.hprof <pid>로 힙 덤프를 만든 다음 Eclipse MAT 또는 VisualVM에서 열어 유지 크기가 가장 큰 객체와 해당 가비지 컬렉션 루트를 찾으십시오.

// Take a heap dump:
jmap -dump:live,format=b,file=heap.hprof $(jps | grep MyApp | cut -d" " -f1)
// Or trigger on OOM:
// -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap.hprof

Eclipse 메모리 분석기(MAT)

MAT의 "누수 의심 항목" 보고서는 유지된 힙이 큰 객체를 자동으로 식별하고 가비지 컬렉션 루트에서 해당 객체까지의 경로를 보여 줍니다. "지배자 트리" 보기에서 시작하여 가장 큰 원인을 찾으십시오.

WeakReference로 누수 방지

캐시 객체나 리스너 객체를 WeakReference로 감싸십시오. 메모리 압박이 발생하면 가비지 컬렉터가 해당 객체를 회수할 수 있습니다. 항상 get() 결과가 null인지 확인하십시오.

Map<String, WeakReference<Image>> imageCache = new HashMap<>();
imageCache.put("logo", new WeakReference<>(loadImage("logo.png")));
Image logo = imageCache.get("logo") != null ? imageCache.get("logo").get() : null;
if (logo == null) logo = reload("logo.png"); // re-load if GCed

LinkedHashMap LRU를 사용한 크기 제한 캐시

LinkedHashMap에서 removeEldestEntry를 재정의하여 캐시 크기를 제한하고 가장 오래 사용되지 않은 항목을 자동으로 제거하십시오.

Map<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
    protected boolean removeEldestEntry(Map.Entry<String, String> e) {
        return size() > 100; // evict when over 100 entries
    }
};

Java Flight Recorder로 할당 프로파일링

JFR(Java Flight Recorder)은 최소한의 오버헤드로 할당 프로파일을 수집합니다. -XX:StartFlightRecording으로 활성화한 후 JDK 미션 컨트롤로 분석하십시오.

// Start a 60-second JFR recording:
java -XX:StartFlightRecording=duration=60s,filename=rec.jfr MyApp
// Or via jcmd:
jcmd <pid> JFR.start duration=60s filename=rec.jfr

누수 수정 체크리스트

정적 컬렉션, 등록 해제되지 않은 리스너, 스레드 풀의 ThreadLocals, 연결 및 스트림 누수(try-with-resources 사용), 외부 객체를 참조하는 내부 클래스, 제거 정책이 없는 캐시를 확인하십시오.

빠른 확인

OutOfMemoryError가 발생할 때 힙을 자동으로 덤프하는 JVM 플래그는 무엇입니까?

복습

Java에서 흔한 누수 원인은 정적 컬렉션, 등록 해제되지 않은 리스너, 스레드 풀에 남은 ThreadLocals, 크기 제한이 없는 캐시입니다. 힙 덤프와 MAT로 감지하십시오. WeakReferences와 크기 제한 자료 구조를 사용하고, 작업이 끝나면 항상 참조를 제거하여 수정하십시오.

자주 묻는 질문

“메모리 누수 감지와 수정” 강의는 무료인가요?

네 — “메모리 누수 감지와 수정” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“메모리 누수 감지와 수정”에서 뭘 배우나요?

일반적인 메모리 누수 패턴(정적 컬렉션, 리스너, 캐시)을 식별하고 수정합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“메모리 누수 감지와 수정” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. JVM 힙 영역과 객체 수명 주기
  2. GC 알고리즘: Serial, G1, ZGC, Shenandoah
  3. 메모리 누수 감지와 수정
  4. GC 튜닝 플래그와 JVisualVM 프로파일링
← Java Academy(으)로 돌아가기