본문 바로가기

Languages/Java

JVM과 GC

JVM

컴파일

Java 소스코드는 Java 컴파일러 javac에 의해 바이트코드로 변환된다. 변환된 바이트코드는 플랫폼에 독립적인 이진 포맷으로, JVM 위에서 실행된다.

클래스 로더

실행 시간에 동적으로 바이트 코드를 로드하고 링크한다.

  • Bootstrap 클래스 로더: JVM 구현의 일부로, Java 기본 클래스를 로드한다.
  • Extension 클래스 로더: 확장 디렉토리에 있는 클래스를 로드한다.
  • Application 클래스 로더: 사용자 정의 클래스와 클래스 경로에 있는 클래스를 로드한다.

Runtime Data Area

Method Area

바이트코드가 저장된다. 클래스의 메타데이터, 상수, 정적 변수 등이 저장된다.

Heap

동적으로 생긴 객체가 저장되는 영역으로 가비지 컬렉션의 대상이 된다.

Stack

스레드마다 하나씩 만들어진다.

메서드가 실행될 때 마다 스택프레임이 생성된다. 메서드 실행이 완료되면 스택프레임이 제거된다.

PC Register

스레드마다 하나씩 만들어진다.

현재 실행중인 명령어의 주소를 저장한다.

Native Method Stack

JNI를 통해 호출된다. Java가 아닌 네이티브 코드 (C, C++)로 작성된 메소드를 위한 스택 영역이다.

Execution Engine

바이트코드를 실행한다. 인터프리터와 JIT(Just-In-Time) 컴파일러 방식이 사용된다.

  • 인터프리터: 바이트코드를 한 번에 한 줄씩 실행한다.
  • JIT 컴파일러: 인터프리터의 단점을 극복하기 위해 도입된 컴파일러로, 바이트코드를 실행 시간에 기계어로 변환해놓고, 해당 코드가 호출될 때 기계어가 실행된다.

JNI (Java Native Interface)

Java 애플리케이션과 네이티브 메소드 간의 상호작용을 가능하게 하는 프레임워크이다. Java 애플리케이션은 JNI를 통해 C, C++ 등의 언어로 작성된 라이브러리를 호출할 수 있다. 이를 통해 시스템 자원이나 하드웨어와 직접 상호작용하는 기능을 구현할 수 있다.

GC (Garbage Collection)

JVM이 Heap 영역의 메모리를 관리하는 과정이다. 더 이상 사용되지 않는 객체에 대해 메모리를 회수한다.

GC의 과정

Mark

  • GC가 스택의 모든 변수를 스캔하면서 각각 어떤 객체를 참조하고 있는지 마킹한다.
  • 마킹한 객체가 참조중인 객체를 찾아서 마킹한다.

Sweep

  • 마킹되지 않은 객체를 제거한다.

GC의 종류

  1. Minor GC
    Eden 영역이 가득 찼을 때 발생하는 가비지 컬렉션으로, Young Generation 영역에서 객체를 정리합니다. 살아남은 객체들은 Survivor 영역(S0 또는 S1)로 이동합니다.
    객체가 Minor GC를 거치며 계속 살아남을 때마다 객체의 나이가 증가한다. 이를 에이징(Aging)이라고 한다.
    객체의 나이가 특정 임계값(age threshold)에 도달하면, 해당 객체는 Young Generation 영역에서 Old Generation 영역으로 이동한다. 이 과정을 객체의 "promotion"이라고 한다.
  2. Major GC
    Old Generation 영역에서 발생하는 가비지 컬렉션이다. Major GC는 성능에 영향을 줄 수 있으므로, 발생 빈도를 최소화해야한다.

Stop-The-World

가비지 컬렉션 중에 일어난다. 모든 애플리케이션 스레드가 잀시 중지되고 GC 작업을 수행하는 스레드만이 실행된다.

일부 가비지 컬렉터는 애플리케이션의 실행과 GC 작업을 동시에 처리하는 동시성(Concurrency)을 활용하여 Stop-The-World의 영향을 최소화한다. 예를 들어, Concurrent Mark Sweep (CMS) GC와 G1(Garbage First) GC는 애플리케이션 스레드가 실행되는 동안에도 가비지 컬렉션 작업을 수행하는 동시성 알고리즘을 사용하여 Stop-The-World의 시간을 줄인다.

GC 최적화

가비지 컬렉션의 성능을 최적화하기 위해 다음과 같은 방법을 사용할 수 있다.

  1. 메모리 사용량 줄이기: 객체의 수명을 줄이고, 객체를 재사용하는 방식으로 메모리 사용량을 줄일 수 있다.
  2. 적절한 가비지 컬렉터 선택: 애플리케이션의 요구 사항에 맞는 가비지 컬렉터를 선택하여 성능을 개선할 수 있다.
  3. JVM 옵션 조정: JVM의 메모리 설정을 조절하여 가비지 컬렉션의 성능을 최적화할 수 있다. 예를 들어, Heap 크기를 조절하거나, Young Generation 영역의 크기를 조절할 수 있다.

Reference

[Java] 자바 JVM 내부 구조와 메모리 구조에 대하여

tech-interview/java.md at master · WeareSoft/tech-interview

https://www.youtube.com/watch?v=AWXPnMDZ9I0

https://www.youtube.com/watch?v=UzaGOXKVhwU&t=4s

https://www.youtube.com/watch?v=vZRmCbl871I&t=4s

'Languages > Java' 카테고리의 다른 글

WeakHashMap과 약한 참조  (0) 2023.08.31
예외처리  (0) 2023.05.24
Primitive Type, Reference Type  (0) 2023.04.25
[Java] HashMap, HashTable, HashSet  (0) 2023.04.12
Object Mapper  (0) 2023.04.07