[JAVA] 메모리 사용 영역

JUJU·2024년 1월 13일
0

JAVA에서 배열에 관해 학습을 하던 중, 배열의 메모리 사용 영역이 C 언어와는 다르다는 것을 알게되었다.

✏️ 메모리 구조 - C

유닉스프로그래밍[2-2학기]에서 배운 내용을 되짚어 보자.
컴파일된 C 언어 프로그램의 모든 데이터는 OS에 의해서 메모리에 적재되고, 메모리는 여러개의 세그먼트로 나뉘어져 관리된다.

segmentsdetails
Code프로그램의 로직이 들어가 있는 바이너리 저장
Data전역 변수와 정적 변수 저장
Heap동적으로 할당되는 변수 저장
Stack함수의 지역변수, 매개변수, 리턴 값, 복귀 주소 등을 저장

Code Segment

  • 프로그램의 실행 바이너리를 저장한다.
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)을 다음과 같은 세부 영역으로 구분한다.

Areadetails
Method클래스별로 정적 필드와 상수, 메소드, 생성자 등을 저장하는 공간
Heap객체와 배열을 저장하는 공간
JVM Stack기본형 변수나 참조형 변수, 매개 변수 등을 저장하는 공간
PC Register쓰레드가 현재 실행 중인 명령의 주소를 저장하는 공간
Native Method StackJava 애플리케이션이 네이티브 라이브러리를 사용할 때, 해당 라이브러리의 메모리 공간

Method

  • 클래스별로 정적 필드와 상수, 메소드, 생성자 등을 저장하는 공간
  • Method 영역에 있는 것은 어느곳에서나 접근 가능 (모든 스레드가 공유)
  • lifetime: 프로그램의 시작 ~ 종료

Heap

  • 객체와 배열을 저장하는 공간
  • Heap 메모리에 있는 객체 또는 배열을 참조하는 변수가 없다면, 이는 공간의 낭비이기 때문에 garbage collector가 메모리를 회수한다.

JVM Stack

  • 기본형 변수나 참조형 변수, 매개 변수 등을 저장하는 공간
  • 메소드가 호출되면 스택 frame을 JVM Stack에 Push 하고, 메소드가 종료되면 Pop
  • 스택 frame이란, 하나의 메서드에 필요한 메모리 덩어리(매개변수, 지역변수, 리턴 값 등)이다
  • lifetime: method 호출 ~ 종료

✏️ 배열 [C] VS [JAVA]

C 언어로 배열을 하나 만들어보자.

int scores[5] = {1,2,3,4,5}; // scores는 지역 변수라 하자

지역 변수인 scores는 Stack 영역에 저장된다.

마찬가지로 Java로 배열을 만들어보자.

int[5] scores = {1,2,3,4,5}; 

scores는 참조 변수이다. 참조 변수는 Stack 영역에 저장되지만, 배열 자체는 Heap 영역에 저장된다.

만약, 2차원 배열이라면 어떻게 저장될까?

참조 변수 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는 왜 포인터 개념이 없을까?

  1. Java는 메모리 관리를 자동으로 처리하는 Garbage Collector가 존재한다. 따라서, 프로그래머가 메모리 관리를 신경쓰지 않아도 된다.
  2. 포인터를 사용하면 보안 문제가 발생할 수 있다.

이러한 이유들 때문에 Java에서는 포인터 대신 참조를 사용한다고 한다.

REFERENCE

혼자 공부하는 자바

profile
개발자 지망생

0개의 댓글

관련 채용 정보