본문 바로가기
Java

[Java] Java의 실행 과정

by 2nyong 2023. 4. 13.

 

  1. 개발자는 자바 소스 파일(.java)를 작성한다.
  2. JDK가 제공하는 자바 컴파일러(javac)를 사용해 소스 파일을 컴파일하여 바이트 코드(.class)를 생성한다.
  3. JVM의 Class Loader가 바이트 코드(.class)를 전달 받아 동적 로딩을 통해 실행에 필요한 클래스들을 로딩하여 JVM 내부의 Runtime Data Area에 로드한다.
  4. JVM의 Execution에 의해 기계에로 해석되어 실행된다.

1. Class Loader

JVM 내부 구조

  • 프로그램 상에서 작성한 모든 클래스, 변수 및 메서드의 정보를 Runtime Data Areas의 Method Area에 배치한다.
  • JVM 내부에 바이트 코드(.class)를 로드하고 링크를 통해 배치하는 작업을 수행한다.
  • 실행될 때 동적으로 클래스를 로드하고 리소스 파일(.jar) 내부에 저장되어 있는 클래스들을 JVM에 로드한다.
  • static(정적) 변수와 메서드는 Runtime Data Areas의 Heap Area에 배치한다.

2. Runtime Data Areas

Runtime Data Areas 구조

 

  • PC의 메모리 역할을 수행하는 영역으로, 자바 프로그램을 실행하여 발생하는 데이터를 저장하는 역할을 한다. 데이터의 속성에 따라 저장하는 영역이 분리되어 있다.

PC Register (Program Counter)

  • Java는Resigter-Base 방식이 아닌 Stacks-Base 방식으로 작동한다.
  • 따라서 JVM은 CPU에 직접 Instruction(연산)을 수행하도록 하지 않고, 현재 작업하는 내용을 CPU에게 연산으로 제공해야 하며, 이를 위한 버퍼 공간으로 PC Register라는 메모리 영역을 사용한다.
  • JVM은 Stack에서 Operand(비연산값)를 뽑아 별도의 메모리 공간인 PC Register에 저장한다.
  • PC Register는 직접적으로 연산을 저장하지 않고 연산의 주소 값을 저장한다. 이 주소 값은 현재 연산이 끝난 뒤에 값을 증가시켜, 해당하는 주소 값의 연산을 실행하게 된다.
  • PC Register는 스레드가 시작할 때 생성되며 스레드마다 하나씩 존재한다.

Native Method Stack

  • 자바 프로그램에 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역이다.
  • JVM은 JINI(Java Native Interface)를 지원하기 때문에 Java 이외의 언어로 작성된 코드를 실행할 때, 바이트 코드로 전환하여 Native Method Stack에 쌓인다.
  • 일반적인 Java 메소드를 실행하는 경우, JVM 스택에 쌓이다가 해당 메소드 내부에 다른 언어의 메소드가 있다면 해당 메소드는 Native Method Stack에 쌓이게 된다.
  • 일반적은 프로그램처럼 커널이 스택을 잡아 독자적으로 프로그램을 실행시키는 영역이다.

Method Area (Metaspace, Static Area, Class Area)

  • Class loader를 통해 클래스(.class) 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 공간이다.
  • 클래스 별로 런타임 상수풀(Runtime Constant Pool), 필드 데이터(Field Data), 메소드 데이터(Method Data), 메소드 코드(Method Code), 생성자 코드(Constructor Code) 등의 정보를 가지고 있으며 모든 스레드가 공유한다.
  • 런타임 상수풀 - 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.

Heap Area

 

  • 객체(인스턴스)와 배열이 생성되는 영역으로, 프로그램을 실행하는 중 생성되는 객체들은 모두 이곳에서 생성된다.

 

Heap Area - Permanent Generation

  • 생성된 객체들의 정보의 주소값이 저장된 공간이다.
  • Class loader에 의해 로드되는 Class, Method 등에 대한 Meta 정보가 저장되는 영역이며 JVM에 의해 사용된다.
  • Reflection을 사용하여 동적으로 클래스가 로딩되는 경우에 사용된다.
    Reflection : 구체적인 클래스 타입을 알지 못해도, 컴파일된 코드를 통해 역으로 클래스의 정보를 알아내는 기법
  • Java 8 이전에는 Pernanent Generation이 Heap Area 내부에 존재했지만 Java 8 이후에 제거되고, Method Area의 Metaspace라고 불리며 Heap Area가 아닌 Native Memory Area에 저장된다. (이전에 제한된 메모리 크기 때문에 발생했던 한계점을 극복하기 위해 변경되었다)

 

Heap Area - New/Young Generation

  • Eden : 객체들이 최초로 생성되는 공간
  • Survivor 0,1 : Eden에서 참조되는 객체들이 저장되는 공간
  • 생명 주기가 짧은 객체를 Garbage Collector의 대상으로 하는 영역이다.
  • Eden 영역에 객체가 가득차게 되면 Garbage Collector에 의해 Eden 영역에 있는 값들을 Survivor 1 영역에 복사하고 이 영역을 제외한 나머지 객체들을 삭제한다.

 

Heap Area - Tenured Generation

  • Old : 이곳의 객체들은 Garbage Collector에 의해 삭제된다.
  • New/Young Generation에서 일정시간 참조되고 있으며, 살아남은 객체들이 저장되는 공간이다.
  • 생명 주기가 긴 객체를 Garbage Collector의 대상으로 하는 영역이다.

Stack Area

  • 프로그램 실행 과정에서 임시로 할당이 되었다가 메서드를 빠져나가면 바로 소멸이 되는 특성의 데이터들을 저장하기 위한 영역이다.
  • 실행되는 메서드 및 중괄호 블록(if statement 등)에 대한 데이터가 저장되는 영역이다.
  • 가장 처음 실행되는 메서드인 main()이 첫 번째로 메모리에 올라가고, 그 다음에 실행되는 메서드들이 위에 쌓이는 구조다.
  • 쌓이는 메서드의 단위를 Stack Frame이라고 부른다.
  • Stack은 메서드를 호출할 때마다 Frame을 추가(Push)하고, 메서드가 종료되면 해당 Frame을 제거(Pop)하는 동작을 수행한다.
  • Frame 내부에는 로컬 변수 Stack이 있으며, 변수가 초기화될 때 이 영역에 생성된다. 변수는 선언된 블록 안에서만 로컬 변수 Stack에 존재하고, 블록을 벗어나면 제거된다.
  • Stack Area의 가장 큰 특징은 멀티 스레드 환경에서 각 스레드가 고유의 스택 영역을 가진다는 점이다.

댓글