[JAVA] 메모리 사용 영역
JAVA의 메모리 사용 영역에 관한 스터디 메모
JAVA에서 배열에 관해 학습을 하던 중, 배열의 메모리 사용 영역이 C 언어와는 다르다는 것을 알게되었다.
✏️ 메모리 구조 - C
유닉스프로그래밍[2-2학기]에서 배운 내용을 되짚어 보자. 컴파일된 C 언어 프로그램의 모든 데이터는 OS에 의해서 메모리에 적재되고, 메모리는 여러개의 세그먼트로 나뉘어져 관리된다.
| segments | details |
|---|---|
| Code | 프로그램의 로직이 들어가 있는 바이너리 저장 |
| Data | 전역 변수와 정적 변수 저장 |
| Heap | 동적으로 할당되는 변수 저장 |
| Stack | 함수의 지역변수, 매개변수, 리턴 값, 복귀 주소 등을 저장 |
Code Segment
- 프로그램의 실행 바이너리를 저장한다.
1 2 3 4
int main(void){ printf("hello world); // hello world는 코드에 속하지 않는다!!! }
Data Segment
- 전역 변수와 정적 변수를 저장하고, 소스코드의 문자열도 여기에 저장한다.
-
초기화 되지 않은 데이터(BSS - Block Started by Symbol)와 초기화 된 데이터로 나뒨다.
- 초기화 되지 않은 변수 –> 실행 파일에 데이터 기록 필요 없음, 실행할 때만 메모리 할당 받음
- 초기화 된 변수 –> 실행 파일에 데이터 기록 필요, 실행 파일의 크기 커짐
Heap Segment
- malloc() 등을 통해 동적으로 할당한 메모리를 저장하는 공간
- 크기가 동적으로 변화함
Stack Segment
- 지역변수, 함수 매개변수, 함수의 리턴값, 함수 복귀 주소 등이 저장됨
- 크기가 동적으로 변화함
✏️ 메모리 구조 - JAVA
JAVA는 컴파일러 언어들 중에서도 특이한 언어이다.
JVM(Java Virtual Machine)이란 OS에 상관없이 Java를 실행할 수 있게 해주는 가상 머신이다. (자세한 내용은 3학년 때 컴파일러와 OS 수업을 들으면 알 수 있을 것 같다)
따라서, Java가 사용하는 메모리 구조를 이해하려면 JVM이 사용하는 메모리 구조를 알아야한다.
JVM은 메모리 영역(Runtime Data Area)을 다음과 같은 세부 영역으로 구분한다.
| Area | details |
|---|---|
| Method | 클래스별로 정적 필드와 상수, 메소드, 생성자 등을 저장하는 공간 |
| Heap | 객체와 배열을 저장하는 공간 |
| JVM Stack | 기본형 변수나 참조형 변수, 매개 변수 등을 저장하는 공간 |
| PC Register | 쓰레드가 현재 실행 중인 명령의 주소를 저장하는 공간 |
| Native Method Stack | Java 애플리케이션이 네이티브 라이브러리를 사용할 때, 해당 라이브러리의 메모리 공간 |
Method
- 클래스별로 정적 필드와 상수, 메소드, 생성자 등을 저장하는 공간
- Method 영역에 있는 것은 어느곳에서나 접근 가능 (모든 스레드가 공유)
- lifetime: 프로그램의 시작 ~ 종료
Heap
- 객체와 배열을 저장하는 공간
- Heap 메모리에 있는 객체 또는 배열을 참조하는 변수가 없다면, 이는 공간의 낭비이기 때문에 garbage collector가 메모리를 회수한다.
JVM Stack
- 기본형 변수나 참조형 변수, 매개 변수 등을 저장하는 공간
- 메소드가 호출되면 스택 frame을 JVM Stack에 Push 하고, 메소드가 종료되면 Pop
- 스택 frame이란, 하나의 메서드에 필요한 메모리 덩어리(매개변수, 지역변수, 리턴 값 등)이다
- lifetime: method 호출 ~ 종료
✏️ 배열 [C] VS [JAVA]
C 언어로 배열을 하나 만들어보자.
1
int scores[5] = {1,2,3,4,5}; // scores는 지역 변수라 하자
지역 변수인 scores는 Stack 영역에 저장된다.
마찬가지로 Java로 배열을 만들어보자.
1
int[5] scores = {1,2,3,4,5};
scores는 참조 변수이다. 참조 변수는 Stack 영역에 저장되지만, 배열 자체는 Heap 영역에 저장된다.

참조 변수 scores는 Stack 영역에 저장되고, 배열은 모두 Heap 영역에 저장된다. 자세한 내용은 이전 포스트를 참고하자: https://velog.io/@jaewon-ju/JAVA-%EB%B0%B0%EC%97%B4%EA%B3%BC-Arraylist
✏️ JAVA는 왜 포인터를 못 쓰게 하는가?
JAVA의 메모리에 관한 공부를 하다가 C언어에서 처럼 %p 형식 지정자를 사용하여 주소값을 출력하려고 했다. 하지만! 오류가 발생했다…Java는 포인터 개념이 없기 때문이었다.
그럼 Java는 왜 포인터 개념이 없을까?
- Java는 메모리 관리를 자동으로 처리하는 Garbage Collector가 존재한다. 따라서, 프로그래머가 메모리 관리를 신경쓰지 않아도 된다.
- 포인터를 사용하면 보안 문제가 발생할 수 있다.
이러한 이유들 때문에 Java에서는 포인터 대신 참조를 사용한다고 한다.
REFERENCE
혼자 공부하는 자바
