본문 바로가기

CS

자바의 자료형과 가상 메모리 공간에 대해

 

자바의 자료형은 기본 자료형과 참조 자료형으로 나뉜다.

 

     기본 자료형 종류 (Primitive Data Type)
        - byte, short, int, long, float, double, boolean, char

     참조 자료형 종류 (Reference Data Type)
        - String, array, Object 등

 

 기본 자료형의 종류를 보면 크기가 고정된 단순한 값들이 기본 자료형으로 분류되는 걸 알 수 있다. 반면 참조 자료형의 종류를 보면 대체로 의미를 가진 값들이 담겨지게 되는데, 자바는 이처럼 의미를 가진 데이터들에 대해 추상화 하여 객체로 다루는 ‘객체 지향’의 특성을 가지고 있어, 참조 자료형으로 구분하게 된다. 그리고 자료형을 이렇게 구분한 데에는 이유가 더 있는데, 바로 저장 방법이 다르고 이로 인한 성능 차이가 있기 때문이다.

 

 

 기본 자료형의 경우 스택 영역에 값을 직접 저장하기 때문에 해당 변수를 바로 가져다 쓸 수 있어 빠른 처리가 가능하다. 이와 달리 참조 자료형의 경우 힙 영역에 실제 값이 저장되고 스택 영역에는 주소만 저장하게 되는데, 사용 시에 부수적인 과정(메모리 할당, 참조 관리, 가비지 컬렉션)이 필요해서 시간이 걸리며 성능 면에서 차이를 보인다.

 

왜 스택 영역과 힙 영역에 나눠서 저장하나요 ? 같이 저장하면 안되나요 ?

 이 질문에 답하기 위해서는 스택 영역과 힙 영역이 뭔지 알아야 한다. 이 영역들은 JVM 이 JAVA로 개발된 프로그램을 실행 할 때 사용하라고 내어준 가상의 메모리에 있는 영역으로 스택과 힙 영역 외에도 코드 영역과 데이터 영역이 있다.

코드 영역 실행할 프로그램의 코드 저장
데이터 영역 전역 변수, 정적 변수 등 저장
힙 영역 동적으로 할당되는 객체들 저장
스택 영역 지역 변수, 매개변수, 함수 호출 정보 등 저장

* 코드 영역과 데이터 영역을 합쳐 ‘메소드 영역’ 또는 ‘스태틱 영역’이라 부르기도 한다.

 

 이렇게 하나의 가상 메모리 공간을 나눠서 저장 및 관리하는 이유는 JAVA 프로그램 실행에 필요한 코드와 데이터 마다 생명 주기가 다르고 그에 따라 메모리에 할당하고 해제하는 방식에 차이가 있기 때문이다

 

 특정 함수가 실행되는 동안에만 필요한 데이터인 지역 변수나 매개 변수, 함수 호출 정보는 짧은 생명 주기를 가지고 있으며 스택 영역에서 저장하게 된다. 스택 영역은 LIFO(Last-In, First-Out) 구조로 되어 있어 가장 최근에 사용된 데이터를 다시 꺼내서 사용하기에 적합하다.

 보다 긴 생명 주기를 갖게 되는 객체나 배열 형태인 참조 자료형의 값들은 대체로 다른 함수에서도 사용되는 등 특정 함수가 끝난 이후에도 데이터가 남아있어야 하는 경우가 많기 때문에 힙 영역에 동적으로 생성 및 관리하게 된다.

 

 이때, 스택 영역에는 직접 데이터를 저장하지만 힙 영역에서는 실제 데이터가 저장된 주소를 저장해두기 때문에 MMU(메모리 관리 유닛) 라는 CPU 내부에 있는 하드웨어 장치에 의해 메모리에 있는 실제 물리적 주소로 변환 후 값을 다시 가져오는 시간이 걸리기 때문에 스택에 저장되는 기본 자료형에 비해 사용 시 비용이 더 들게 된다.

 

더보기

이런 경우 객체가 통으로 힙 영역에 저장되어 지는데, 이를 기본 자료형이 힙 영역에 저장된 거라 생각하면 안되고, 그저 기본 자료형을 포한 한 ‘객체’가 힙 영역에 저장된 거라 이해해야한다.

더보기

참조 자료형이 생성될 때 힙 영역에 실제 객체가 저장된 후, 매개변수로는 실제 객체를 가리키는 주소 값만 전달되어 스택 영역에 그 주소 값이 저장되는 것으로 매개변수로 전달 된 참조 자료형이 스택 영역에 저장되는 거라고 생각해선 안된다.

 

가상 메모리 공간을 누가 나누는 건가요?

 가상 메모리 공간은 CPU 아키텍처와 운영체제가 함께 나누게 되는데, 프로세스 별로 할당되는 가상 메모리 공간의 크기는 주로 CPU 아키텍처의 비트 수와 운영체제의 구현 방식에 따라 결정된다. 윈도우 사용자라면 이런저런 프로그램을 다운 받을 때 32비트 와 64비트 중에서 선택하여 다운 받아본 경험이 있을텐데, 그때 봤던 비트가 저 비트다.

 

32비트와 64비트, 살짝 더 알아보자면...

 32비트 시스템의 경우 가상 메모리 공간은 2의 32승으로, 4GB 가 되고, 64비트 시스템은 2의 64승인 16EB(엑사바이트) 가 되는데, 실제로는 CPU의 성능 이슈로 다 사용하지 못하고 일부만 사용되어 약 48비트(128~256TB)정도의 공간만 사용하게 된다.

 여기서 실제 사용 가능한 공간의 크기 (32비트시스템=4GB / 64비트시스템=약 256TB)는 또다시 사용자 모드 영역과 커널 모드로 나눠지게 되며 일반적으로는 각각 절반씩 나눠 갖게 되는데, 사용자 모드와 커널 모드로 나누는 이유는 간단하게 알고 넘어가자면, 사용자 모드 애플리케이션이 커널 영역에 직접 접근 하는 것을 막아 운영체제의 핵심 기능을 보호하고 시스템의 안전성 유지하기 위해서이다.

 

가상 메모리 공간의 각 영역별 크기는 어떻게 나눠지나요 ?

 누가 나누는건지 알아봤으니 어떻게 나눠지는지도 알아보자면, 각 영역마다 필요한 크기만큼만 할당 받아 사용하게 되는데 코드 영역과 데이터 영역의 경우 프로그램 시작 초기에 프로그램의 크기만큼 할당 받게 되고, 스택 영역과 힙 영역의 경우 함수 호출이 증가하거나 새로운 객체 생성 요청이 들어오는 등 메모리 요청이 생길 때마다 동적으로 메모리 공간을 할당받게 된다.

 이때, 가상 메모리 공간을 ‘페이지’라는 블록 단위로 나누어 할당 받게 되는데 범용 운영체제(Windows, Linux, macOS)는 기본적으로 페이지의 크기를 4KB 로 사용한다. 할당 받는 과정을 조금 상세히 설명해보자면, 예를 들어 스택이 총 18KB 공간이 필요하다면 5개의 페이지(20KB)를 할당 받고 2KB의 공간을 남기게 된다. 이 남는 부분은 내부 단편화라 하는데 단편화에 대해서는 여기서 추가 설명하지 않겠다.

 

 

'CS' 카테고리의 다른 글

IP 주소가 생긴 이유 (인터넷의 탄생)  (0) 2025.06.23