티스토리 뷰

Programming/Java

[Java] JVM 메모리 구조

감성적인 개발자 2022. 3. 9. 21:29

JVM

자바의 가장 큰 특징 중 하나는 운영체제에 독립적이라는 것이다. 즉, 윈도우에서 만들어진 자바 프로그램은 리눅스, 맥 os 에서도 동작할 수 있다. OS 위에서 이러한 독립성을 제공해주는 것이 JVM(Java Virtual Machine)이며 기본적으로 동작하는 과정은 다음과 같다.

 

자바 프로그램 실행 과정

사용자가 만든 Java 소스코드는 컴파일러를 거쳐 클래스 파일(바이트코드로 번역)로 만들어진다. 이후 만들어진 바이트 코드를 JVM이 읽어 어떤 운영체제든 실행가능하도록 만들어진다. 

이러한 구조를 통해 Java프로그램은 운영체제에 독립적이라고 할 수 있다. 하지만 Java 응용프로그램이 통신하는 JVM은 운영체제(Window, Linux, Mac)에 종속적이다. 즉, 운영체제에 적절한 JVM이 설치되어 있어야 다른 운영체제에서 작성된 Java 프로그램을 실행할 수 있게 된다.

 

 

JVM 메모리 구조

이러한 JVM이 어떻게 동작하는지, 구조는 어떤지 알아보겠습니다. JVM 구조는 크게 4가지로 나눌 수 있습니다.

 

1. Garbage Collector

힙 메모리 영역에 생성된 객체들 중에서 참조되지 않은 객체들을 탐색 후 제거하는 역할을 한다.. 이때, GC가 역할을 하는 시간은 언제인지 정확히 알 수 없다.

 

2. Execution Engine

메모리에 적재된 클래스(바이트 코드)들을 기계어로 변경해 명령어 단위로 실행하는 역할을 한다. 초기에는 명렁어를 하나 하나 실행하는 인터프리터 방식을 사용해 속도가 느렸으나, JIT 컴파일러 방식으로 이를 보완했다.

 

3. Class Loader

JVM 내로 클래스 파일을 로드하고, Runtime Data Area 형태로 메모리에 적재 하는 작업을 수행하는 모듈이다. 런타임 시에 동적으로 클래스를 로드한다.

 

 

4. Runtime Data Area

 Method Area

프로그램 실행 중 사용되는 클래스의 클래스파일(.class)을 JVM이 분석하여 해당 클래스에 대한 정보를 저장한다. 이 때, 클래스 멤버 변수, 메소드 정보, 타입(클래스 혹은 인터페이스)정보, static, final 변수 등이 함께 생성된다. 

 

 Heap Area

프로그램 실행 중 생성되는 인스턴스들은 모두 Heap 영역에 저장된다. 즉, new 연산자를 통해 생성된 인스턴스 변수들은 모두 이 영역에 존재하며, 메서드가 종료되어도 가비지 콜렉터에 의해 정리되기 전 까지 계속 존재한다.

 

 Call Stack(호출 스택)

메서드가 호출되는 순간 작업하기 위한 메모리 공간을 제공한다. 해당 메서드가 실행되는 동안, 지역변수, 매개변수, 연산의 중간결과 등이 저장되며 작업을 마치면 할당했던 메모리공간은 반환된다.

Stack 영역인 만큼 FILO 구조를 가지는데 A작업 수행 중 B메서드가 호출되면, 새로 호출된 B메서드를 위한 공간이 할당되고 B메서드에 제공된 메모리 영역이 반환되기 전에는 A작업은 수행되지 않는다.

 

StackTest.java 예시 코드

public class StackTest {

	public static void main(String[] args) {
		calculator(10, 20);
	}
	
	public static void calculator(int x, int y) {
		calculatorPrint(x + y);
	}
	
	public static void calculatorPrint(int z) {
		System.out.println("calculatorPrint: " + z);
	}

}

StackTest.java 프로그램 실행 시 Call Stack의 변화

  1. 프로그램 시작과 동시에 main 메서드가 호출된다.
  2. main 메서드 안에서 calculator() 를 호출하면 main 메서드는 대기상태로 변경되며 호출된 함수가 수행된다.
  3. calculator() 안에서 다시 calculatorPrint()를 호출하면 이전 과정이 반복된다. 호출된 calculatorPrint()가 완료되기 이전에는 calculator() 와 main 메서드는 수행되지 않는다.
  4. calculatorPrint()에서 println()을 호출한다. println()메서드에 의해 화면에 출력을 수행한다.
  5. println() 수행이 완료되어 해당 메모리 영역은 반환되고 다시 calculatorPrint()영역으로 돌아온다.
  6. calculatorPrint() 메서드는 더 이상 수행할 코드가 없으므로 calculatorPrint() 종료되고 메모리영역은 반환된다. 해당 메서드를 호출했던 calculator() 메서드로 돌아온다.
  7. calculator() 메서드는 더 이상 수행할 코드가 없으므로 calculator()는 종료되고 메모리 영역은 반환된다. 해당 메서드를 호출했던 main 메서드로 돌아온다.
  8. main메서드 또한 더 수행할 코드가 없으므로 Call Stack은 완전히 비워지게 되고, StackTest.java 프로그램은 종료된다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
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 31
글 보관함