[Java] Runtime Data Areas

하비·2024년 10월 13일
1

Java

목록 보기
7/13

Class Loader 글 이후로 이어서 포스팅 해보겠다.

JVM에는 Class Loader, Runtime Data Areas, Execution Engine 이렇게 3개로 구성되어 있다.
Class Loader에서 class 파일들을 동적으로 로드하고, Runtime Data Areas에 올려준다고 했었다. 이제 Runtime Data Areas를 알아보자

처음 시리즈부터 다시 보고 싶다면?
JDK, JRE, JVM부터 다시 보기

Runtime Data Areas

JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.
런타임 데이터 영역은 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack으로 나눌 수 있다.

Method Area와 Heap 영역은 Thread들이 서로 공유하는 영역이기 때문에 동시성 문제를 고려해야 한다.

Method Area

JVM이 시작될 때 생성되는 공간으로 바이트 코드(.class)를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간이다.
JVM이 동작하고 클래스가 로드될 때 적재돼서 프로그램이 종료될 때까지 저장된다.

Runtime Constant Pool

Method Area 영역에 포함되지만 독자적 중요성을 띈다.

Heap Area

힙 영역은 메서드 영역과 함께 모든 쓰레드가 공유하며, JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역이다.
즉, new 연산자로 생성되는 클래스와 인스턴스 변수, 배열 타입 등 Reference Type이 저장되는 곳이다.
Method Area 영역에 저장된 클래스만이 생성이 되어 적재된다.

Stack Area

int, long, boolean 등 기본 자료형을 생성할 때 저장하는 공간으로, 임시적으로 사용되는 변수나 정보들이 저장되는 영역이다.

PC 레지스터(Program Counter Register)

쓰레드가 시작될 때 생성되며, 현재 수행중인 JVM 명령어 주소를 저장하는 공간이다.
JVM 명령어 주소는 쓰레드가 어떤 부분을 무슨 명령으로 실행해야할 지에 대한 기록을 가지고 있다.

Native Method Stack

자바 코드가 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역이다.

전체적인 과정


그림에서 보이는 metaspace가 method 영역이다.
method 영역이 Java 8 이상에서는 PermGen이 Metaspace로 대체되었다.

전체 실행 코드는 다음과 같다.

  • MainCustomer.java
public class MainCustomer extends Customer {
	String hobby;
	public MainCustomer() {
	}
	
	public MainCustomer(String name, int age, String address, String hobby) {
		super(name, age, address);
		this.hobby= hobby;
	}
	
	public String customerInfo() {
		return  super.customerInfo()+" 취미:"+hobby;
	}
}
  • Customer.java
public class Customer {
	String name;
	int age;
	String address;
	
	public Customer( ) { 
		this("ssafy", 12, "서울");
	}
	
	public Customer(String name, int age, String address){
		this.name = name;
		this.age = age;
		this.address = address;
	}
	
	public boolean equals(Object o) {
		return this == o;
	}
	String customerInfo() {
		return "이름:"+name+" 나이:"+age+" 주소:"+address;
	}
}
  • InheritanceTest.java
public class InheritacneTest {

	public static void main(String[] args) {
		MainCustomer mcust = new MainCustomer("ssafy", 12, "서울", "코딩");
		System.out.println(mcust.customerInfo());
	}

}

이렇게 3개의 자바 파일이 있고, MainCustomer는 customer를 상속받고 있다. 이 코드에서 main 문을 실행할 때 전체적으로 runtime data 영역에서 어떻게 동작하는지 보자.

MainCustomer mcust=new MainCustomer("ssafy", 12, "서울", "코딩");
System.out.println(mcust.customerInfo());

이 코드를 실행할 때, 그림처럼 동작이 된다.

자세히 살펴보면,

  1. 처음에 main이 있는 클래스 정보를 클래스 로더가 metaspace에 저장한다.(그림에서는 InheritanceTest)
  2. MainCustomer mcust 변수를 설정할 때, stack 영역의 main 메소드에 해당하는 스택 프레임이 생성되고, 이 프레임 안에 mcust 변수를 저장한다.
  3. new를 실행할 때, metaspace에 MainCustomer 정보와 Customer 정보를 저장해놓는다. Heap 영역에는 MainCustomer의 변수와 Customer의 변수들을 초기화된 상태를 저장해놓는다.
  4. MainCustomer("ssafy", 12, "서울", "코딩") 부분을 실행할 때, stack에 MainCustomer 생성자를 위한 스택 프레임이 생성된다. MainCustomer에 대한 변수들 저장과 heap 영역의 위치를 저장한다. heap data를 갱신한다.
  5. MainCustomer에서 생성자를 만들 때, Customer 생성자를 생성해 초기화해주기 때문에 Customer 프레임도 stack 영역에 넣는다.

이렇게 Runtime Data Areas에 대해서도 알아보았다.
다음에는 Execution Engine에 대해 알아보겠다.

profile
멋진 개발자가 될테야

0개의 댓글