JVM Memory Structure

Java 메모리 구조

자바에서 사용하는 메모리 모델의 구조를 이해하면 자바 프로그램이 많은 도움이 된다.

JVM(Java Virtual Machine)

Java 프로세스는 JVM이라는 가상 시스템에서 실행된다. 이와 같은 구조는 컴파일된 Java 클래스 파일(bytecode)를 다양한 OS 환경에서 실행 가능하게 해준다.

JVM

Java 메모리 영역 구조

모든 자바 프로그램은 자바 가상 머신(JVM)을 통해서 실행된다. 자바 프로그램이 실행되면, JVM은 운영 체제로부터 해당 프로그램을 수행할 수 있도록 필요한 메모리를 할당받는다.

이렇게 할당받은 메모리를 JVM은 메모리 공간을 효율성을 높이기 위해 메모리 공간을 용도에 따라 다음과 같이 여러 영역으로 구분하여 나누서 관리한다.

JVM Runtime Data Area

Runtime Data Area 운영체제로부터 할당받은 메모리 영역이며, 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.
크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 나눌 수 있다.

메소드(method) 영역 / Static 영역

메소드(method) 영역은 자바 프로그램에서 사용되는 클래스에 대한 정보와 함께 클래스 변수(static variable)가 저장되는 영역이다.
JVM은 자바 프로그램에서 특정 클래스가 사용되면 해당 클래스의 즉, 자바 바이트 코드인 클래스 파일(*.class)를 읽어 들인 클래스와 인터페이스 대한 런타임 상수 풀(runtime contant pool), 멤버 변수(필드), 클래스 변수(Static 변수), 생성자와 메소드를 저장하는 공간이다.

이 영역에 저장된 내용은 프로그램이 시작전에 로드되고 프로그램이 종료시 소멸된다.
런타임 상수 풀에는 컴파일 타임에 알려진 숫자 리터럴(literal)부터 런타임에 확인되어야 하는 메소드 및 필드 참조에 이르기까지 여러 상수가 포함된다.

리터널(literal)은 컴퓨터 과학 분야에서 고정된 값을 의미한다. 상수는 변하지 않는 변수를 말하고, 리터럴은 변하지 않는 값(데이터)를 말한다.

힙(heap) 영역

힙(heap) 영역은 자바 프로그램에서 사용되는 모든 클래스 객체(인스턴스) 변수가 저장되는 영역으로, JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역이다.

프로세스 처리를 실행하는 과정에서 동적으로 변화하는 데이터는 기본적으로 여기에 할당된다. 즉, JVM은 자바 프로그램에서 new 연산자를 사용하여 인스턴스가 생성되면, 해당 인스턴스의 정보를 힙 영역에 저장한다.
힙 영역은 메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.

그리고 스택 영역의 변수가 힙 영역의 인스턴스를 참조하고 있다가 더이상 참조하지 않게 된다면, 자바 가상머신의 가비지 컬렉션을 통해 인스턴스는 제거된다.

가비지 컬렉션은 인스턴스가 참조되지 않을 때마다 실행되는 것은 아니다. 그렇게 되면 가비지 컬렉션 호출만으로 많은 리소스를 사용하게 되기 때문에 프로그램의 성능이 저하 될 것이다. 따라서 가비지 컬렉션 알고리즘에 따라 실행된다.

힙 영역의 사용 기간 및 스레드 공유 범위는 아래와 같다.

  • 객체가 더 이상 사용되지 않거나 명시적으로 null 선언 시
  • GC(Garbage Collection) 대상
  • 구성 방식이나 GC 방법은 JVM 벤더마다 다를 수 있다.
  • 모든 스레드에서 공유한다.

오랫동안 동일한 프로세스로 실행되는 응용 프로그램에서는 이 힙 영역에서 메모리 사용을 최적화하는 것이 중요하다. 할당할 크기를 지정할 때는 구체적으로 옵션은 아래와 같다.

-Xms20m -Xmx100m

위와 같이 지정하게 되면 아래와 같은 설정이 된다.

  • 힙 영역에 할당할 메모리의 초기 크기: 20MB
  • 힙 영역에 할당할 메모리의 최대 크기: 100MB

스택(stack) 영역

스택(stack) 영역은 자바 프로그램에서 메소드가 호출될 때 메소드의 스택 프레임이 저장되는 영역이다.

JVM은 자바 프로그램에서 메소드가 호출되면, 메소드의 호출과 관계되는 지역 변수와 매개변수를 스택 영역에 저장한다. 이렇게 스택 영역은 메소드의 호출과 함께 할당되며, 메소드의 호출이 완료되면 소멸한다. 택 영역에 저장되는 메소드의 호출 정보를 스택 프레임(stack frame)이라고 한다.

스택 영역은 Push으로 데이터를 입력하고, Pop으로 데이터를 출력한다. 이러한 스택은 후입선출(LIFO, Last-In First-Out) 방식에 따라 동작하므로, 가장 늦게 저장된 데이터가 가장 먼저 나오게 된다.

스택 영역은 메모리의 높은 주소에서 낮은 주소의 방향으로 할당된다.

PC Register

  • 현재 수행 중인 JVM 명령 주소를 갖는다. CPU의 PC와 같은 역할이라고 할 수 있다.
  • 프로그램 실행은 CPU에서 인스트럭션(Instruction)을 수행한다.
  • CPU은 인스트럭션을 수행하는 동안 필요한 정보를 CPU 내 기억장치인 레지스터에 저장한다.
  • 연산 결과값을 메모리에 전달하기 전 저장하는 CPU내 기억장치 (보통 CPU가 명령어를 처리하는 과정에서 수행하는 동안 필요한 정보를 Register라는 CPU내의 기억장치에 저장해 둔다. 이는 CPU에 종속적일 수 밖에 없다. 그렇기 때문에 자바의 철학을 실형하기 위해서는 이러한 CPU내 Register의 역할을 JVM 상에 논리적인 메모리 영역으로 구현.)

Native Method Stack Area

자바 외 언어로 작성된 네이티브 코드를 위한 Stack이다.
즉, JNI(Java Native Interface)를 통해 호출되는 C, C++ 등의 코드를 수행하기 위한 스택이다.
네이티브 메소드의 매개 변수, 지역 변수 등을 바이트 코드로 저장한다.

참조