JVM 기술면접 Q&A

Jihye Gim·2026년 5월 20일

Codeit SB11

목록 보기
17/22

JVM 기술면접 Q&A 20선


1. JVM의 클래스 로딩 과정을 설명해주세요.

A. 클래스 로딩은 3단계입니다.

  • Loading: .class 파일을 읽어 메모리에 올림. Bootstrap → Extension → Application ClassLoader 순으로 위임(Delegation).
  • Linking:
    • Verification: 바이트코드 유효성 검증
    • Preparation: static 변수 기본값 할당
    • Resolution: 심볼릭 참조를 실제 메모리 참조로 변환
  • Initialization: static 초기화 블록 실행, static 변수에 실제 값 할당.

2. ClassLoader의 계층 구조와 위임 모델을 설명해주세요.

A.

Bootstrap ClassLoader (JVM 내장, C++로 구현)
    └── Extension ClassLoader (jre/lib/ext)
            └── Application ClassLoader (classpath)

Parent Delegation Model: 클래스 로드 요청이 오면 자신이 먼저 처리하지 않고 부모 ClassLoader에 위임. 부모가 못 찾을 때만 자신이 로드. → java.lang.String 같은 핵심 클래스를 사용자가 임의로 바꾸는 것을 방지.


3. JIT(Just-In-Time) 컴파일러란?

A. JVM은 처음에 바이트코드를 인터프리터로 실행합니다. JIT 컴파일러는 자주 실행되는 코드(Hot Spot)를 감지해 네이티브 코드로 컴파일하여 캐시합니다.

  • C1 컴파일러: 빠른 컴파일, 적은 최적화 (클라이언트 모드)
  • C2 컴파일러: 느린 컴파일, 강한 최적화 (서버 모드)
  • Java 8+: Tiered Compilation으로 C1 → C2 단계적 적용.

4. GC 알고리즘 종류와 특징을 설명해주세요.

A.

  • Serial GC: 단일 스레드. 소규모 애플리케이션용.
  • Parallel GC (Java 8 기본): 멀티스레드 Minor GC. 처리량(Throughput) 중심.
  • CMS (Concurrent Mark Sweep): GC 스레드와 앱 스레드 동시 실행. 낮은 지연시간. Java 14에서 제거.
  • G1GC (Java 9+ 기본): Region 단위 관리. STW 예측 가능. 대용량 Heap에 적합.
  • ZGC / Shenandoah: 초저지연. 대부분의 작업이 동시 실행. 수백 GB Heap에서도 ms 미만 STW.

5. Young Generation과 Old Generation의 차이는?

A.

  • Young Generation: 새로 생성된 객체. Eden + Survivor0 + Survivor1으로 구성. Minor GC가 빠르게 처리.
  • Old Generation: Young에서 오래 살아남은 객체(tenured). Major GC는 더 느리고 긴 STW.
  • 객체 이동 흐름: Eden → (Minor GC 생존) → Survivor → (age 임계치 초과) → Old Generation.
  • -XX:MaxTenuringThreshold로 Old로 승격되는 나이 조정 가능.

6. STW(Stop-The-World)란 무엇이고 줄이는 방법은?

A. GC 수행을 위해 모든 애플리케이션 스레드를 일시 정지하는 현상. GC 루트에서 객체 그래프를 안전하게 탐색하기 위해 필요합니다.

  • 줄이는 방법:
    • G1GC/ZGC 등 저지연 GC 알고리즘 선택
    • Heap 크기 적정하게 설정 (너무 크면 GC 시간 증가)
    • 객체 생성 줄이기 (객체 풀링, 불변 객체 재사용)
    • -XX:MaxGCPauseMillis로 목표 STW 시간 설정

7. OutOfMemoryError의 종류와 원인은?

A.

  • Java heap space: Heap 메모리 부족. 메모리 누수 또는 Heap 크기 부족.
  • GC overhead limit exceeded: GC가 98% 시간을 사용하지만 2%도 회수 못할 때.
  • Metaspace: 클래스 메타데이터 영역 부족. 동적 클래스 생성 과다(Reflection, 프록시).
  • Unable to create new native thread: OS 스레드 한계 초과.
  • Direct buffer memory: NIO DirectByteBuffer 과다 사용.

8. Java에서 스레드 동작 방식과 JVM 스레드 모델은?

A. Java 스레드는 OS 스레드(Kernel Thread)와 1:1로 매핑됩니다(Java 19 이전).

  • 스레드 생성 비용이 높아 ThreadPool 사용이 필수.
  • Java 19+ Virtual Thread (Project Loom): JVM이 관리하는 경량 스레드. OS 스레드 1개에 수천 개의 Virtual Thread 매핑. I/O 대기 시 OS 스레드를 블로킹하지 않고 다른 Virtual Thread 실행.

9. JVM 튜닝 시 주요 JVM 옵션을 설명해주세요.

A.

-Xms512m          → 초기 Heap 크기
-Xmx2g            → 최대 Heap 크기
-XX:+UseG1GC      → G1GC 사용
-XX:MaxGCPauseMillis=200  → STW 목표 시간
-XX:MetaspaceSize=256m    → Metaspace 초기 크기
-XX:+HeapDumpOnOutOfMemoryError → OOM 시 Heap Dump
-verbose:gc       → GC 로그 출력
  • -Xms-Xmx를 동일하게 설정하면 Heap 재할당 오버헤드 제거.

10. Metaspace와 PermGen의 차이는?

A.

  • PermGen (Java 7 이하): JVM Heap 내 고정 크기 영역. 클래스 메타데이터 저장. 크기 초과 시 OutOfMemoryError: PermGen space.
  • Metaspace (Java 8+): Native 메모리(OS 메모리) 사용. 기본적으로 자동 확장. 클래스 메타데이터를 Heap 밖으로 분리해 PermGen OOM 문제 해결. -XX:MaxMetaspaceSize로 최대치 설정 가능.

11. Heap Dump와 Thread Dump의 차이는?

A.

  • Heap Dump: 특정 시점의 Heap 메모리 전체 스냅샷. 객체 수, 점유 크기, 참조 관계 포함. OOM 분석에 사용. jmap -dump 또는 -XX:+HeapDumpOnOutOfMemoryError.
  • Thread Dump: 모든 스레드의 현재 스택 상태 스냅샷. 데드락, 스레드 블로킹 분석에 사용. jstack <pid> 또는 kill -3 <pid>.

12. 데드락(Deadlock)의 발생 조건과 감지 방법은?

A. 데드락의 4가지 필요 조건(Coffman 조건):

  1. 상호 배제: 자원을 하나의 스레드만 점유
  2. 점유와 대기: 자원을 가진 채 다른 자원 대기
  3. 비선점: 다른 스레드의 자원 강제 해제 불가
  4. 순환 대기: 스레드 간 원형으로 자원 대기

감지: Thread Dump에서 BLOCKED 상태의 스레드와 순환 참조 확인. JConsole/VisualVM의 Detect Deadlock 기능 활용.


13. Java의 동시성 컬렉션(Concurrent Collection)이란?

A. 멀티스레드 환경에서 안전하게 사용 가능한 컬렉션.

  • ConcurrentHashMap: 버킷 단위 락. Collections.synchronizedMap()보다 성능 우수.
  • CopyOnWriteArrayList: 쓰기 시 배열 복사. 읽기가 압도적으로 많을 때 유리.
  • BlockingQueue (LinkedBlockingQueue, ArrayBlockingQueue): 생산자-소비자 패턴에 활용.
  • ConcurrentLinkedQueue: lock-free 큐.

14. JVM의 인라이닝(Inlining) 최적화란?

A. JIT 컴파일러가 메서드 호출을 호출 코드 안으로 직접 삽입하는 최적화.

  • 메서드 호출 오버헤드 제거 (스택 프레임 생성/해제 비용 절감)
  • 추가 최적화(상수 폴딩, 데드 코드 제거) 가능
  • final 메서드, private 메서드, 작은 메서드에 잘 적용됨
  • -XX:MaxInlineSize로 인라이닝 크기 임계값 조정 가능

15. GC 로그에서 확인해야 할 지표는?

A.

  • GC 빈도: Minor GC가 너무 자주 → Eden 크기 조정 필요
  • STW 시간: Major GC의 STW가 길면 G1/ZGC 전환 고려
  • Heap 사용률: GC 후에도 Heap이 계속 높으면 메모리 누수 의심
  • Promotion Failure: Young → Old 승격 실패. Old가 가득 차면 발생
  • Concurrent Mode Failure (CMS): 동시 GC 진행 중 Old가 가득 찬 경우

16. 바이트코드(Bytecode)란 무엇인가요?

A. Java 소스코드를 javac로 컴파일한 플랫폼 독립적인 중간 코드. .class 파일에 저장되며 JVM이 해석/실행합니다.

  • javap -c ClassName으로 바이트코드 확인 가능
  • iload, istore, invokevirtual 등 JVM 명령어로 구성
  • WORA(Write Once Run Anywhere)의 핵심: 바이트코드는 어느 OS의 JVM에서든 동일하게 실행

17. Escape Analysis란?

A. JIT 컴파일러가 객체의 참조 범위를 분석해 Heap 대신 Stack에 할당할 수 있는지 판단하는 최적화.

  • 객체가 메서드 밖으로 탈출(Escape)하지 않으면 Stack 할당 → GC 부담 감소
  • Stack Allocation: Escape 없는 객체를 Stack에 할당
  • Scalar Replacement: 객체를 분해해 필드를 레지스터/Stack 변수로 처리
  • -XX:+DoEscapeAnalysis (기본값 활성화)

18. Java에서 finalize() 메서드의 문제점은?

A. finalize()는 GC가 객체를 수거하기 전에 호출되는 메서드지만 심각한 문제가 있습니다.

  • 호출 보장 없음: JVM이 finalize()를 언제, 또는 아예 호출하지 않을 수 있음
  • 성능 저하: finalize()가 있는 객체는 GC가 2번 처리 (Finalization Queue)
  • 부활 가능성: finalize()에서 this 참조를 저장하면 객체가 GC 대상에서 제외
  • Java 9+에서 @Deprecated. try-with-resourcesCleaner로 대체.

19. AOT(Ahead-Of-Time) 컴파일과 JIT의 차이는?

A.

  • JIT: 실행 중에 Hot Spot을 감지해 컴파일. 워밍업 시간 필요. 런타임 정보로 최적화 우수.
  • AOT: 실행 전에 미리 네이티브 코드로 컴파일. 워밍업 없음. 즉시 최고 성능.
  • GraalVM Native Image: AOT 컴파일로 JVM 없이 실행 가능한 바이너리 생성. 시작 시간 수십 ms, 메모리 사용량 대폭 감소. 컨테이너/서버리스 환경에 유리.

20. JVM 모니터링 도구에는 어떤 것들이 있나요?

A.

  • jps: 실행 중인 JVM 프로세스 목록
  • jstat: GC, 클래스 로딩, JIT 컴파일 통계 실시간 확인. jstat -gcutil <pid> 1000
  • jmap: Heap Dump 생성, Heap 요약 정보
  • jstack: Thread Dump 출력
  • jconsole / VisualVM: GUI 기반 종합 모니터링
  • APM (Pinpoint, Datadog, New Relic): 실무에서 분산 추적 + JVM 지표 통합 모니터링
profile
Rookie

0개의 댓글