ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION752 / 1500
언어·런타임난이도 중하5분 답변 목표 · 보강본

Java 앱을 반복 재배포할수록 메타스페이스가 늘어납니다. 클래스 로더는 어떤 참조 때문에 회수되지 않을 수 있나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

클래스와 로더의 수명은 도달 가능성에 영향을 받습니다. 재배포한 로더를 전역 캐시·스레드·ThreadLocal·등록 callback이 계속 참조하면 옛 클래스 집합이 회수되지 않을 수 있습니다.

동작 원리와 전제

앱이 만든 executor나 타이머가 종료되지 않으면 context class loader나 작업 객체가 옛 로더를 붙잡을 수 있습니다. static 필드가 있다는 이유만으로 항상 영구 누수는 아니고 어느 살아 있는 root에서 연결되는지 봐야 합니다.

선택과 실패 처리

종료 훅에서 등록 해제·스레드 종료·캐시 정리를 수행하고 라이브러리 전역 레지스트리의 수명을 확인합니다. 강제 GC만 반복하거나 메타스페이스 한도를 늘려 원인을 숨기지 않습니다. 로더별 클래스 수·heap 참조 경로·재배포 횟수를 대조합니다.

구체적인 사례와 검증

재배포 전 로더가 만든 listener를 프로세스 전역 registry에 등록하고 해제하지 않았다면 registry가 살아 있는 동안 옛 callback과 클래스가 연결될 수 있습니다. 단순히 앱 변수에 null을 대입해도 그 경로는 남습니다. thread dump와 heap 참조 분석으로 root를 찾아 등록·해제 수명을 고칩니다. 테스트에서는 동일 기능을 여러 번 로드·종료하고 클래스 수와 로더 수가 계속 증가하는지 봅니다. 강제 GC 뒤 즉시 감소하지 않는다는 이유만으로 누수를 확정하지는 않지만, 분명한 강한 참조가 남아 있으면 그 경로를 제거해야 합니다. 메타스페이스 증가는 일반 객체 heap 증가와 다른 관측이 필요합니다.

여러 번 로드·사용·종료한 뒤 로더가 수집 가능해지는지 시험합니다. native 메모리와 일반 heap·metaspace 지표를 구분합니다. 클래스 언로드는 요청 순간 즉시 일어난다는 보장이 아니므로 장기 추세와 실제 참조 원인을 확인하겠습니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • 핵심 구분: 클래스와 로더의 수명은 도달 가능성에 영향을 받습니다.
  • 선택 조건: 종료 훅에서 등록 해제·스레드 종료·캐시 정리를 수행하고 라이브러리 전역 레지스트리의 수명을 확인합니다.
  • 검증 기준: 여러 번 로드·사용·종료한 뒤 로더가 수집 가능해지는지 시험합니다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • 앱 객체 참조를 지우거나 GC를 호출하면 옛 클래스 로더는 반드시 즉시 사라진다고 한다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

  • 외부 참조를 제거한 뒤에도 살아 있는 root가 객체를 붙잡는지 어떻게 확인하나요?
  • 재사용 실행 단위에 이전 사용자 문맥이 남지 않게 어떤 설정·정리 수명을 두나요?
  • 새 작업을 막은 뒤 진행 중 작업·공유 풀·로그를 어떤 순서로 종료하나요?

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기