JVMMemoryAndStatic

1. JVM

자바 메모리 구조를 이해하기 전에, 먼저 JVM(Java Virtual Machine)에 대해 간단히 살펴보겠습니다.

1.1 JVM이란?

  • Java Virtual Machine의 약자. 자바 소스 코드를 컴파일해서 만들어진 바이트코드(.class) 를 OS에 종속되지 않고 실행해주는 가상 머신입니다.

  • JVM만 설치되어 있으면, 어느 운영체제에서든 같은 .class 파일을 실행할 수 있는 것이 자바의 큰 장점입니다.

1.2 JVM 실행 순서

  1. 소스 컴파일 .java → 자바 컴파일러 → .class(바이트 코드)

  2. 클래스 로더(ClassLoader) .class 파일을 읽어서 JVM 내로 로딩, 필요한 클래스를 동적으로 가져옴.

  3. JVM 런타임 영역에 적재 로딩된 클래스가 메모리(Method Area 등)에 올라오고, 프로그램이 실행됩니다.

1.3 JVM의 Run Time Data Area

자바 메모리 영역을 설명할 때는 보통 다음 5가지 구성을 말합니다:

  • Heap Area

  • Static/Method Area

  • Stack Area

  • PC Register

  • Native Method Stacks

아래 이미지는 메인 메서드가 호출될 때 JVM이 어떻게 구동되는지를 간단히 보여줍니다.

JVM 구동방식 (메인메서드 호출)
  1. 클래스 로더가 .class 파일을 로드

  2. 정적 영역(Static or Method)에 클래스 정보 배치

  3. 힙/스택 등 런타임 영역에서 코드가 실행

  4. .class 내부 정보를 활용해 프로그램이 동작

2. 자바의 메모리 영역이란?

자바 애플리케이션이 실행되면, JVM은 OS로부터 메모리를 할당받아 여러 개의 영역으로 나누어 사용합니다. 이 메모리 공간을 Runtime Data Area라 부르며, 보통 Method(Static) 영역, Stack 영역, Heap 영역이 핵심입니다.

런타임 데이터 영역(간략)
  • Method(Static) 영역

  • Stack 영역

  • Heap 영역

  • PC Register, Native Method Stacks (자세한 설명은 아래 참조)

메모리를 효율적으로 구성해야 성능이 좋아집니다. 잘못 구성하거나 지나친 재귀 호출 등으로 StackOverflowError가 발생할 수도 있으므로 주의가 필요합니다.

3. 자바 변수의 종류

메모리 영역을 살펴보려면, 먼저 자바에서 변수를 어떻게 분류하는지 알아야 합니다.

자바 변수의 종류
  1. 클래스 변수 (static 변수)

    • 클래스 레벨에서 선언, 모든 객체가 공유 가능.

  2. 인스턴스 변수 (멤버 변수)

    • 객체를 생성(new)할 때 만들어지며, 각 객체마다 다른 값을 가짐.

  3. 매개변수

    • 메서드 호출 시 전달하는 값을 저장, 메서드가 종료되면 소멸.

  4. 지역 변수

    • 메서드 블록 { ... } 안에서 선언 후, 블록이 끝나면 사라짐.

각 변수의 생성 시점

  • 클래스 변수(static) → 클래스 로딩 시

  • 인스턴스 변수 → 객체(new) 생성 시

  • 지역 변수, 매개변수 → 메서드(또는 블록) 실행 시점에 생성

4. 자바 메모리 구조

4.1 자바 메모리 구조 - 비유

자바 메모리 구조 (비유)
  • 메서드 영역: 클래스 정보를 보관 (붕어빵 틀에 비유)

  • 스택 영역: 메서드 호출 시마다 쌓이는 영역

  • 힙 영역: new로 생성된 객체(붕어빵)가 놓이는 곳

4.2 자바 메모리 구조 - 실제

자바 메모리 구조 (실제)
  1. 메서드 영역(Method Area)

    • 프로그램 실행에 필요한 클래스 정보, 필드/메서드/생성자 코드가 보관.

    • static 변수(static 영역), 런타임 상수 풀도 이곳에 속함.

  2. 스택 영역(Stack Area)

    • 실행 스택을 형성, 메서드 호출 시마다 스택 프레임이 생성.

    • 지역 변수, 매개변수, 임시 연산 결과 저장.

    • 메서드 종료 시 해당 프레임이 제거.

  3. 힙 영역(Heap Area)

    • 객체(인스턴스) 및 배열이 생성되는 영역, GC(가비지 컬렉션)가 참조되지 않는 객체를 회수.

    • 자바 7 이전에는 PermGen 영역이 존재했고, 8 이상에서는 Metaspace 사용 등 구조 변화가 있음.

💡 스택은 쓰레드별로 하나씩 존재, 힙/메서드 영역은 여러 쓰레드가 공유.

5. 메서드 영역 (Method Area)

5.1 클래스 정보

JVM이 클래스 파일을 로드할 때, 해당 클래스의 메타데이터(타입, 변수명, 메서드 구조 등)를 메서드 영역에 저장합니다.

5.2 런타임 상수 풀

문자열 리터럴("hello" 등)이나 상수화된 값들이 모여 재사용되는 곳. (자바 7부터 일부는 힙으로 이전)

5.3 static 정보 (정적)

  • 정적 변수와 메서드는 프로그램 시작 시 클래스 로딩과 함께 메모리상에 올라와 종료 때까지(또는 언로드 전) 유지.

  • 동적으로 생성되는 인스턴스와 달리, 이미 결정된 시점에 고정(정적)으로 존재한다고 해서 static이라 부름.

  • 클래스 변수 static 변수, 정적 변수등으로 불리니 헷갈리지 않게 주의

static 메서드가 멤버 변수를 사용할 수 없는 이유

  • static 메서드는 인스턴스 없이 호출 가능.

  • 인스턴스 변수는 new로 객체를 만들어야 생기므로, static 메서드에서는 직접 접근 불가.

  • 단, 내부에서 객체를 새로 생성하거나 매개변수로 참조를 받으면 인스턴스 변수를 쓸 수 있음.

6. 스택 영역(Stack)

메서드 실행 시 사용되는 메모리.

  1. 메서드 호출 → 스택 프레임 생성 → 지역 변수, 매개변수 할당.

  2. 메서드가 종료되면 해당 스택 프레임 소멸.

  3. 재귀나 무한 호출 등으로 스택이 꽉 차면 StackOverflowError.

7. 힙 영역(Heap)

객체(인스턴스)와 배열이 생성되는 영역.

Heap 구조
  • 가비지 컬렉션이 참조되지 않는 객체를 제거.

  • 여러 쓰레드가 공유하므로 동시성 문제 시 동기화가 필요.

  • 자바 8 이후 PermGen이 Metaspace로 변경되는 등 내부 구조가 다를 수 있음.

8. 힙 vs 스택 메모리 차이점

힙 vs 스택
  1. 공유 범위

    • 스택: 쓰레드마다 독립 (안전)

    • 힙: 모든 쓰레드가 공유 (동기화 고려 필요)

  2. 저장 데이터

    • 스택: 지역 변수, 매개변수, 참조 변수

    • 힙: 인스턴스(객체), 배열 전체

  3. 메모리 에러

    • 스택: StackOverflowError

    • 힙: OutOfMemoryError(Heap Space)

9. 정리

  • 자바 프로그램 시작 시, JVM은 클래스 정보/메서드/생성자 코드메서드 영역에 로드.

  • 필요 시, new힙에 객체를 생성.

  • 메서드가 호출될 때마다 스택 프레임이 생성되어 지역 변수/매개변수를 처리, 종료 시 소멸.

  • static 변수와 메서드는 클래스 로딩 시 메서드 영역에 자리 잡고, 프로그램 끝날 때까지 유지 가능.

결론

  • **클래스 변수(static)**는 클래스 로딩 시점,

  • 인스턴스 변수new로 객체 생성 시점,

  • 지역 변수는 메서드 실행 시점에 각각 생성됨.

  • 메모리 구조를 정확히 이해하면 성능 최적화, 오류(스택 오버플로우, 메모리 부족) 대처, 객체 지향 설계 등에 크게 도움이 된다.

Last updated