JVM 메모리 구조


 

런타임 데이터 영역이란 JVM으로 돌아가는 애플리케이션을 실행할 때 필요한 데이터가 올라가는 영역이다.

크게 Method, Heap, Stack영역과 PC Register, Native Method Stack이 있는데 이번에는 앞에 3개의 영역만 다뤄 보려 한다.

 

 

메서드 영역 (Method Area)


 

메서드 영역은 Class Area, Static Area 라고도 불리며 바이트 코드가 클래스 로더를 거쳐 넘어온 정보를 저장하는 공간이다.

이렇게 넘어온 정보들은 프로그램이 종료될 때까지 유효하다.

 

저장되는 정보

  • Static Field의 이름, 데이터 타입, 접근 제한자 정보
  • Method의 이름, return 타입, 메서드의 매개변수, 접근 제한자 정보 
  • Type(class, enum, intepace)정보와 부모의 정보

상수 풀 (Runtime Constant Pool)

메서드 영역에 위치한 영역으로 다음과 같은 조건을 만족하면 상수풀에 저장될 수 있다.

  1. 할당된 데이터가 숫자 리터럴(primitive literal) 이거나 문자열 리터럴(String literal) 혹은 이 둘이 결합된 값일 것.
    • ex) 1, "A", 1+"A"
  2. static final로 선언되어야할 것.
    • ex) static final int num = 1;

이 두 조건이 만족하면 constant pool에 저장이 된다.

 

String은 String pool에 저장되는 거 아닌가?

결론부터 말하면 맞다.

그럼 상수 풀과 이름이 같기 상수 풀이 메서드 영역에 독립적으로 존재하는 것처럼 문자열 풀도 상수 풀에 독립적으로 존재할 거 같은 느낌이 든다.

 

하지만 String pool은 힙 영역에 존재한다.

그렇다면 위에 설명한 static final String은 어떻게 상수 풀에 있는가 설명하면 상수 풀에 있는 문자열 정보는 사실 리터럴이 아니라 레퍼런스(Reference)가 저장이 된다.

 

그림으로 보자면 다음과 같다 

 

힙 영역 (Heap Area)


힙 영역에는 new 연산자로 생성되는 인스턴스(Class, 배열 등)가 담기는 곳이다.

 

이곳에 담기는 정보들은 null로 선언하거나 GC(Garvage Collction)에 의해 해제될 때까지 유효하다.

 

GC란?

Java에서 메모리 누수가 없이 안전하게 객체를 해제하기 위해 JVM이 자동으로 수행하는 메모리 관리 기법이다.

 

GC에서는 크게 2가지 영역이 있다

 

Young 영역(Young Generation)

  • Eden
    • new연산자를 통해 새로 생성된 인스턴스가 위치
    • eden에 할당 공간이 부족하면 servivor로 보내진다
  • servivor 0 / servivor1
    • 최소 한 번 이상 살아남은 인스턴스들이 위치하는 곳
    • servivor1과 2둘 중 하나는 꼭 비어있어하는 규칙이 있다.

Old 영역(Old Generation)

  • Young generation에서 살아남은 인스턴스들이 위치하는 곳.
  • young 영역보다 메모리가 크게 할당되고 GC가 적게 발생한다.
  • young generation에서만 GC가 발생하면 minor GC, Old generation까지 GC가 발생하면 full GC라고 불린다.

 

스택 영역 (Stack Area)


스택 영역은 메서드의 호출과 관계되는 지역 변수와 매개변수를 저장합니다.

 

stack은 LIFO 구조로 마지막에 들어온 값이 먼저 나가는 방식이다.

 

메서드 호출 시마다 각각의 스택 프레임(호출된 메서드만을 위한 공간)이 생성되고 수행이 끝나면 프레임별로 삭제된다.

 

Heap 영역에서 저장하는 것과 스택 영역에서 저장하는 것에 혼돈이 올 수 있는데 

String a = new String("A");

라고 했을 때 new String("A")는 힙 영역, a는 스택 영역에 저장된다.

 

스택 영역은 스레드마다 존재하며 스레드에 메모리가 충분하지 않다면 StackOverFlow가 발생할 수 있다.

 

정리


'CS > JAVA' 카테고리의 다른 글

JVM - 클래스 로더(Class Loader)  (4) 2025.08.04

클래스 로더란?


자바는 메모리를 효율적으로 관리하기 위해 모든 클래스를 한 번에 로딩하는 것이 아닌 필요할 때만 지연 로딩하는 방식을 사용한다. 이 동작을 가능하게 해 주는 것이 클래스 로더이다.

 

로드(loading)

  • 자바 바이트코드(.class)를 메소드 영역 다음과 같은 정보를 저장한다.
    • 로드된 클래스와 그 부모 클래스
    • 어떤 타입으로 선언됐는지 ex) class, interface, enum
    • 변수나 메서드 정보

링크(Linking)

  • 검증 : 로드된 클래스가 JVM 명세에 맞는지(오버/언더플로우, 올바른 명령어 등)를 검사한다.
  • 준비 : static 필드들의 메모리를 슬롯을 할당하고 기본값으로 초기화한다.
  • 분석 : 클래스에 심볼릭 참조(이름 기반 참조)를 직접 참조(메모리 주소)로 바꾼다.

초기화(Initialization)

  • 클래스 로딩과 링크가 끝난 뒤, 실제로 값을 초기화한다.

 

 

클래스 로더 종류


부트스트랩 클래스 로더(Bootstrap Class Loader)

  • 최상위 클래스 로더이며 최소한의 자바 클래스를 로드한다.

확장 클래스 로더(Extension Class Loader)

  • Bootstrap 로더의 자식으로, JRE 설치 경로의 lib/ext/ (또는 java.ext.dirs) 디렉토리에 놓인 확장 JAR들을 로드합니다.

애플리케이션 클래스 로더(Application Class Loader)

  • 자바 프로그램 실행 시 지정한 Classpath에 있는 클래스 파일 혹은 jar에 속한 클래스들을 로드합니다.
  • 일반적으로 개발자가 작성한 .class 확장자 파일이 이에 해당한다
  • System Class Loader라고도 부른다.

 

 

클래스 로더의 3가지 원칙


위임원칙(Delegation Priciple)

  • 클래스 로딩 요청을 받으면 부모 클래스 로더에게 로드를 위임하고 최상위 클래스로더(Bootstrap)에서 부터 찾기 시작하여 찾지못하면 찾을 때 까지 자식에게로 계속 내려간다.
  • 이를 중복 로드를 하지않고 일관성을 확보한다.

가시성 원칙(Visibility Priciple)

  • 하위 클래스 로더는 상위 클래스 로더가 로딩한 클래스를 볼 수 있지만, 반대로 상위로더는 하위 로더가 로딩한 클래스를 볼 수 없다.
  • 이로써 시스템 전반의 클래스 충돌을 방지하고, 모듈화된 구조를 유지할 수 있다. 

유일성 원칙(Uniqueness Principle)

  • 동일한 이름의 클래스를, 부모가 이미 로드했다면 자식 로더는 다시 로드하지 않는다
  • 위임 원칙 덕분에 애플리케이션 전역에서 클래스의 중복없는 로드를 보장한다.

'CS > JAVA' 카테고리의 다른 글

JVM 메모리 구조  (5) 2025.08.06

+ Recent posts