자바의 메모리 구조는 프로그램의 실행 동안 사용되는 다양한 종류의 데이터를 저장하고 관리하는 방식을 정의하며, 메서드 영역, 스택 영역, 힙 영역 3개로 나눌 수 있다.
메서드 영역 ( Method Area )
- 클래스 수준의 정보 ( 클래스 구조, 메소드 코드, 상수, 정적 변수 등) 을 저장한다.
- JVM 하나당 메서드 영역이 있으며, 모든 스레드가 이 영역을 공유 한다.
- 클래스 정보(구조) : 클래스의 실행 코드 ( 바이트 코드), 필드, 메서드와 생성자 코드 등 모든 실행 코드가 존재한다.
- 클래스 구조(틀) 메서드의 코드, 생성자 정보, 상수 등 클래스와 관련된 모든 정보가 메서드 영역에 로딩된다.
- static 영역 : static 변수들을 보관한다. ( 변수와 메서드 )
- 정적 변수는 클래스가 JVM에 로딩 될때 처음 한번 초기화 하고 그 이후로는 해당 클래스의 모든 객체가 이 변수에 대해 동일한 값을 공유 한다.
스택 영역 (Stack Area )
스택 영역은 메서드의 실행을 관리하는데 사용된다.
- 스레드 할당 : JVM에서 각 스레드는 자신만의 스택 영역을 가집니다. 즉, 스택 영역은 스레드마다 고유하며, 다른 스레드와 공유하지 않습니다.
- LIFO(Last In, First Out) : 스택은 후입선출 구조를 가지고 있어 가장 마지막에 들어간 요소가 가장 먼저 나옵니다.
- 메서드 호출관리 : 스택 영역은 메서드의 호출과 실행을 관리 합니다. 각 메서드 호출에 대해 스택 프레임이라는 블록이 스택에 푸쉬 됩니다.
- 메모리 관리 : 스택 영역은 메모리가 엄격하게 관리 되는 영역이며, 메서드 호출과 종료에 따라 자동으로 메모리가 할당되고 해제 됩니다.
- 스레드 안정성 : 각 스레드가 자신만의 스택을 가지므로, 스택 영역의 데이터는 다른 스레드와 격리되어 안전성을 제공합니다.
- 실행 속도
스택 프래임
스택 프래임은 특정 메서드의 호출과 관련된 정보를 포함하는 데이터 구조입니다. 각 스택 프레임에는 다음과 같은 정보가 포함 됩니다.
- 로컬 변수 : 메서드 내에서 선언된 모든 변수
- 매개 변수 : 메서드로 전달된 모든 매개변수
- 연산 중간 결과 : 메서드 실행 중 발생하는 중간 계산 결과
- 리턴 값 : 메서드에서 반환된느 값
- 리턴 주소 : 메서드 실행이 끝난 후에 값이 이동할 인스턴스 참조 값 또는 주소
작동 방식
- 메서드 호출 : 메서드가 호출될 때, JVM은 해당 메서드를 위한 새로운 스택 프레임을 생성하여 스택에 push 합니다.
- 메서드 실행 : 메서드가 실행되면 로컬 변수와 매개변수가 스택 프레임에 저장되며, 메서드 내부에서 이루어지는 모든 계산은 해당 스택 프레임 내에서 처리 됩니다.
- 메서드 종료 : 메서드 실행이 완료되면 리턴 값을 전달하고 해당 메서드는 스택에서 제거 (pop) 됩니다.
힙 영역 (Heap Area)
모든 자바 어플리케이션의 런타임 데이터가 저장 되는 영역입니다.
- 객체 공간의 저장 : 힙 영역은 자바 프로그램에서 생성되는 모든 객체와 배열을 저장합니다.
- new 키워드로 생성된 인스턴스 및 배열
- 가비지 컬렉션 (Garbage Collection) : 힙 영역은 가비지 컬렉터에 의해 관리되며, 가비지 컬렉터는 더이상 참조 되지 않는 인스턴스를 자동으로 감지하고 메모리에서 해제 합니다.
public class GarbageCollectionDemo {
public static void userInfo() {
// 이 메서드 내에서 객체를 생성합니다.
Person person = new Person();
// 메서드가 끝나면 'person'에 대한 참조는 사라집니다.
String name = person.getName();
// 참조가 사라지면 gc에 의해 자동으로 힙영역의 인스턴스는 제거 됩니다.
}
public static void main(String[] args) {
// 객체를 생성합니다.
userInfo();
}
}
class Person {
int count;
String name;
public String getName() {
return name;
}
}
- JVM 공유 : 힙 영역은 JVM 내의 모든 스레드에 의해 공유 되므로 여러 스레드가 동일한 객체에 접근할 수 있습니다.
작동 방식
- 객체 생성 : 프로그램 실행 중 객체가 생성 되면, 해당 객체의 데이터는 힙 영역에 저장됩니다.
- 참조 관리 : 객체는 스택 영역의 변수나 다른 객체의 필드롤 통해 참조 됩니다.객체에 대한 할성 참조가 없어지면 해당 객체는 가비지 컬렉션의 대상이 됩니다.
- 메모리 할당 및 해제 : 객체가 생성될 때 메모리가 할당되고, 가비지 컬렉터에 의해 더 이상 필요하지 않은 객체가 제거될 때 메모리가 해제 됩니다.
JVM 에서의 실행 과정 요약
메서드 영역은 JVM의 핵심 구성 요소 중 하나로, 실행 중인 어플리케이션의 클래스 정보를 저장하며, 메서드 영역은 주로 클래스 수준의 데이터를 다루며 실행 과정은 다음과 같다
- 로딩 단계 : JVM은 어플리케이션을 실행할 때 필요한 클래스 파일들을 메모리에 로딩하고, 클래스 로더가 .class 파일을 읽어 클래스 정보를 메서드 영역에 저장한다.
- 저장되는 정보 :
- 메서드 영역 : 클래스와 인터페이스에 관한 메타 데이터, 상수, 정적 변수, 그리고 실제 메서드의 바이트 코드가 저장된다. 여기에는 정적 메서드 뿐만 아니라 인스턴스 메서드의 코드도 포함된다.
- 힙영역 : 모든 클래스 인스턴스와 배열 할당 , 이 영역은 객체가 생성되고(new) 가비지 컬렉터에 의해 제거된다.
- 스택영역 : 각 스레드의 실행 스택이며, 메서드 호출 시 각 호출에 대한 스택 프래임이 생성되어 로컬 변수와 매개 변수를 저장한다. 메서드가 종료 되면 해당 스택 프레임은 제거 된다.
- PC 레지스터 : 현재 실행중인 JVM 명령어의 주소
- 네이티비 메서드 스택 : 자바 외의 언어로 작성된 네이티브 메서드를 위한 스택
- 메서드 실행 요청 ( 호출 ) : 프로그램에서 특정 메서드를 호출하면 JVM은 메서드 영역에서 해당 메서드의 정보(바이트코드)를 찾는다.
- 스택 프레임 생성 : 메서드 호출 시 JVM 스택 영역에 해당 메서드를 위한 새로운 스택 프래임이 생성된다. 이 스택 프레임은 메서드의 로컬 변수, 매개 변수, 리턴 값, 연산 중간 결과 등을 포함 한다.
- 메서드 실행 : JVM은 메서드 영역에서 읽어들인 메서드의 바이트 코드를 해석하고 실행 한다. 이 실행 과정은 스택 프레임 내에서 이루어지며, 메서드의 코드가 처리 된다.
- 메서드 종료 : 메서드의 실행이 완료 되면 해당 스택프레임은 스택에서 제거 되고, 메서드가 값을 반환 하는 경우, 이 값은 호출자에게 전달 된다.
- 가비지 컬렉터 : 클래스 인스턴스나 메서드의 실행이 완료되고 더 이상 참조되지 않는 객체들은 가비지 컬렉터에 의해 정리 된다. 그러나 메서드 영역은 가비지 컬렉터 대상이 아니고 힙 영역의 인스턴스들이 제거 된다.
참조
'자바' 카테고리의 다른 글
final, 상수 (0) | 2023.12.14 |
---|---|
static (0) | 2023.12.13 |
Stream & Optional & Parallel Stream (0) | 2023.12.12 |
Stream (0) | 2023.12.12 |
슬기롭게 주석 사용하기 (0) | 2023.12.12 |