일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- LifeCycle
- 객체지향 프로그래밍 5가지 원칙
- java thread 예제
- 안드로이드 스튜디오 커스텀 다이얼로그
- java
- 변수
- 안드로이드 스튜디오 style
- savedinstancestate
- 안드로이드 스튜디오 custom dialog
- 이중for문 사용 안하기
- 아파치 엔진엑스
- apache nginx
- 리사이클러뷰 아이템 재사용
- 안드로이드 스튜디오 tts
- 안드로이드 스튜디오 인터넷 연결 확인
- 안드로이드 디자인패턴
- 안드로이드 스튜디오 반복되는 레이아웃 코드
- Kotlin
- edittext 연결
- Thread
- 디자인 패턴 예제
- 안드로이드 스튜디오 인터넷 연결 안되어 있을 때
- apache란
- AAC
- hilt error
- 자바 스레드 예제
- dagger error
- 다른 객체 리스트의 비교
- 아파치란
- recyclerview item recycle
- Today
- Total
Sam Story
Java - JVM 메모리 구조 , Stack, Heap 본문
오늘은 JVM 의 메모리 구조에 대해서 포스팅 해보려 한다.
JVM 의 경우 지난번 JAVA 버전에 대한 포스팅을 할 때 간단하게 다루었었다.
JVM (Java Virtual Machine)은 자바 프로그램이 실행되는 환경을 제공하는 가상 머신이다.
자바 코드의 실행 과정을 관리하고, 플랫폼 독립성을 가능하게 하는 핵심 컴포넌트이다.
간단히 정리하면 우리가 입력한 자바코드를 컴퓨터는 바로 인지하지 못하기 때문에
컴퓨터가 알 수 있는 0과 1의 바이트 코드로 변환시켜주는 역할을 하는게 JVM 이다.
이러한 JVM 의 메모리 구조는 5개의 영역으로 구성되어 있다.
1. Method Area
- 클래스 정보, 메서드 코드, static 변수, 상수 풀 등을 저장하는 영역
- 모든 쓰레드에서 공유
- JVM이 시작될 때 생성되며, 프로그램이 종료될 때 해제
2. Heap
- 동적으로 생성된 객체와 배열이 저장되는 영역
- 모든 쓰레드에서 공유
- Garbage Collector가 이 영역을 관리
3. Stack
- 각 쓰레드별로 개별적으로 생성되는 영역
- 메서드 호출 정보(스택 프레임), 지역 변수, 매개변수 등을 저장
- 메서드가 호출되면 스택 프레임이 생성되고, 종료되면 해제
4. PC Register
- 각 쓰레드가 현재 실행 중인 명령어의 주소를 저장하는 작은 메모리 영역
- 쓰레드별로 개별적으로 존재
5.Native Method Stack
- VM 외부에서 실행되는 네이티브 코드(C/C++)를 지원하기 위해 사용
이러한 구조에서 중요한 두 축인 Heap과 Stack에 대해서 좀 더 다루어 보겠다.
Stack
- 용도: 함수 호출과 관련된 지역 변수, 매개변수, 리턴 주소 등을 저장
- 특징:
- LIFO (Last In, First Out) 후입선출 구조: 마지막에 넣은 데이터가 먼저 나온다.
- 자동 관리: 함수가 호출되면 필요한 메모리를 스택에 할당하고, 함수가 끝나면 메모리를 자동으로 해제
- 고정 크기: 운영체제가 정한 제한된 크기로 작동.
- 빠른 속도: 메모리 접근이 매우 빠르다.
지난번 포스팅에서 다루었었던 자료구조 Stack에서 동일한 속성들도 보인다.
Heap
- 용도: 동적 메모리 할당(Runtime에 메모리를 직접 할당하거나 해제) 시 사용
- 특징:
- 크기 유연: 프로그램이 실행되는 동안 필요에 따라 메모리를 할당받는다.
- 수동 관리: 프로그래머가 메모리를 할당하고, 사용이 끝나면 명시적으로 해제해야 한다. (Java에서는 가비지 컬렉터가 관리)
- 느린 속도: 스택보다 접근 속도가 느리다.
예제
코드로 보며 좀 더 쉽게 이해해보자.
public class Main {
public static void main(String[] args) {
int num = 10; // 스택에 저장
char c = 'a'; // 스택에 저장
}
}
여기서 초기화 해준 '10' 과 'a' 라는 값은 직접 Stack에 저장된다.
원시타입 데이터의 경우 Stack에 직접 데이터가 저장된다.
그렇다면 참조형 자료형들은 어떻게 저장되는가?
간단한 데이터 클래스인 Student 클래스를 만들어주고
Student class
public class Student {
String name;
int age;
Student(String name , int age) {
this.name = name;
this.age = age;
}
}
아래 코드처럼 student 객체를 만들어 줬을 때 데이터는 어떻게 할당되는가?
public class Main {
public static void main(String[] args) {
Student student = new Student("Sam",20);
}
}
20 이라는 int 값은 원시타입이고 "Sam" 이라는 값은 참조 타입이니
20은 Stack에 저장되고 "Sam"은 Heap에 저장되는가?
아래 그림을 보며 정답을 확인해보자.
Stack에서는 student 객체의 Heap 주소값을 갖게 되고
Heap에서는 student 객체의 name 공간과 age공간을 할당받는다
name 공간에는 "Sam" 이라는 값의 주소값을 할당받고
age 공간에는 20이라는 원시타입 값이 있으므로 데이터가 20으로 저장되고
"Sam" 이라는 주소값 안에 "Sam" 데이터가 저장되는 것이다.
생성자를 이용한 초기화가 아닌 student 객체의 변수를 직접 호출하여 값을 초기화 하여도
메모리 저장방식은 똑같다.
간단하게 정리해 보자면
Stack은 단기적인 데이터를 관리하고,
Heap은 장기적으로 관리해야 하는 데이터를 저장한다고 이해하면 쉬울 것 같다.
'JAVA' 카테고리의 다른 글
Java - Stream (0) | 2025.03.14 |
---|---|
JAVA - Stack (1) | 2024.11.30 |
JAVA - 인터페이스 (2) | 2024.11.22 |
JAVA - 추상클래스 (0) | 2024.11.21 |
JAVA - 의존 역전 원칙 (2) | 2024.10.20 |