JAVA에서 배열에 관해 학습을 하던 중, 배열의 메모리 사용 영역이 C 언어와는 다르다는 것을 알게되었다.
유닉스프로그래밍[2-2학기]에서 배운 내용을 되짚어 보자.
컴파일된 C 언어 프로그램의 모든 데이터는 OS에 의해서 메모리에 적재되고, 메모리는 여러개의 세그먼트로 나뉘어져 관리된다.
segments | details |
---|---|
Code | 프로그램의 로직이 들어가 있는 바이너리 저장 |
Data | 전역 변수와 정적 변수 저장 |
Heap | 동적으로 할당되는 변수 저장 |
Stack | 함수의 지역변수, 매개변수, 리턴 값, 복귀 주소 등을 저장 |
int main(void){
printf("hello world);
// hello world는 코드에 속하지 않는다!!!
}
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 애플리케이션이 네이티브 라이브러리를 사용할 때, 해당 라이브러리의 메모리 공간 |
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의 메모리에 관한 공부를 하다가 C언어에서 처럼 %p 형식 지정자를 사용하여 주소값을 출력하려고 했다. 하지만! 오류가 발생했다...Java는 포인터 개념이 없기 때문이었다.
그럼 Java는 왜 포인터 개념이 없을까?
- Java는 메모리 관리를 자동으로 처리하는 Garbage Collector가 존재한다. 따라서, 프로그래머가 메모리 관리를 신경쓰지 않아도 된다.
- 포인터를 사용하면 보안 문제가 발생할 수 있다.
이러한 이유들 때문에 Java에서는 포인터 대신 참조를 사용한다고 한다.
혼자 공부하는 자바