Java

[JVM 밑바닥까지 파헤치기] 2. 자바 메모리 영역과 메모리 오버플로

noahkim_ 2024. 12. 19. 17:21

저우즈밍 님의 "JVM 밑바닥까지 파헤치기" 책을 정리한 포스팅 입니다


1. 런타임 데이터 영역

프로그램 카운터

  • 스레드의 현재 실행중인 명령어 바이트코드 줄 번호 표시기
    • 바이트코드 인터프리터는 이 카운터의 값을 바꿔 다음에 실행할 바이트코드 명령어를 기억함
  • 멀티스레딩 시, 가장 최근에 실행된 명령어의 지점을 복원하는데 쓰임
  • 네이티브 메서드 실행 시, 비어있음

 

JVM 스택

  • 메서드를 실행하는 스레드의 메모리 모델
  • 각 메서드가 호출될 때마다 스택 프레임을 만들어 관련 정보를 기록

 

지역 변수 테이블
  • 컴파일 타임 정보 
    • 기본 데이터 타입, 객체 참조, 반환 주소 타입
  • 슬롯 단위 (32bit)

 

피연산자 스택
  • 계산에 필요한 값 저장

 

동적 링크 및 메서드 반환값
  • 호출자와 피호출자 간의 관계 유지

 

네이티브 메서드 스택

  • 자바 애플리케이션에서 사용할 수 있는 가장 큰 메모리
  • 객체 인스턴스 보관
  • 논리적으로 연속되도록 할당됨

 

가비지 컬렉터가 관리
  • 세대별로 나뉨
    • young generation: eden, survivor
    • old generation
  • 메모리 회수와 할당을 더 빠르게 하기 위함

 

스레드-로컬 할당 버퍼 (TLAB)
  • 스레드별로 객체를 효율적으로 할당

 

메서드 영역

런타임 상수 풀
  • 내용
    • 클래스 파일 정보 (클래스 버전, 필드, 메서드)
    • 상수 풀
    • 메서드 코드
  • 동적
    • 런타임에 추가될 수 있음
    • String.intern()

 

다이렉트 메모리

물리 메모리를 직접 할당
  • JVM의 메모리 영역은 아님

 

NIO에서 사용되는 메모리
  • 채널, 버퍼 기반 I/O

 

2. 핫스팟 가상 머신에서의 객체 들여다보기

객체 생성

new 명령의 매개 변수가 심벌 참조인지 확인
  • 상수 풀 내의 클래스인지 확인
  • 로드 확인
    • 로딩 - 해석 - 초기화
    • 로딩되지 않았으면 로드해야 함
  • 객체를 담을 메모리 할당
    • 힙의 여유 목록에서 할당됨
    • 멀티스레드인 경우, 동기화 or TLAB 방식을 사용하여 할당

 

객체에 필요한 설정을 셋팅
  • 어느 클래스의 인스턴스
  • 클래스의 메타정보
  • 해시코드
  • GC 세대나이

 

객체 메모리 레이아웃

객체 헤더
  • 마크 워드
    • 객체의 런타임 데이터
    • 해시 코드, GC 세대 나이, 락 상태 플래그, 락, 마크 타임스탬프
  • 클래스 워드
    • 객체의 클래스 메타데이터를 가리키는 포인터
  • 배열 길이

 

인스턴스 데이터
  • 객체가 실제로 담고 있는 정보
    • 필드 값
    • 부모 클래스
  • 크기가 같은 데이터끼리 함께 할당됨
    • 메모리 효율을 위함

 

정렬 패딩
  • 자리 확보
    • 8바이트 정수배
  • 메모리 접근 성능 최적화

 

객체 접근

  • 스택에서 힙의 객체에 접근하는 방법

 

다이렉트 포인터 방식 (기본)
  • 객체를 바로 가리킴
    • 내부에 객체의 클래스 데이터를 가리키는 포인터 존재
  • 오버헤드가 적음

 

핸들 방식
  • 힙에 핸들 저장용 풀이 별도로 존재
    • 객체의 인스턴스 데이터를 가리키는 포인터
    • 객체의 클래스 데이터를 가리키는 포인터
  • 객체의 위치가 바뀌는 상황에서도 참조 자체에 손 댈 필요 없음

 

3. OutOfMemory 예외

힙 오버플로

  • 객체가 보관되는 공간에 초과가 일어나는 경우

 

매개 변수
  • -Xms: 최소 크기
  • -Xmx: 최대 크기
  • -XX: +HeapDumpOnOutOfMemoryError: 오버플로 발생 시점의 힙 메모리 스냅숏을 덤프 (파일 형식)

 

네이티브 메서드 스택 오버플로

  • 스레드가 요구하는 스택 깊이가 가상 머신이 허용하는 최대 깊이보다 클 경우
  • 가용 메모리가 부족해 더 이상 스택을 확장할 수 없는 경우

 

매개 변수
  • -Xss: 스택 크기

 

메서드 영역과 런타임 상수 풀 오버플로

매개 변수
  • -XX: MetaspaceSize
  • -XX: MaxMetaspaceSize
  • -XX: MinMetaspaceFreeRatio: 최소 메타스페이스 여유 공간 비율 설정

 

네이티브 다이렉트 메모리 오버플로

매개 변수
  • -XX: MaxDirectMemorySize