본문 바로가기

Java

[Java] JVM 메모리 구조

728x90
반응형
자바 가상 머신이라고 불리는 JVM은 자바 프로그램을 실행하고, 다른 언어로 작성된 것도 자바 btye code로 컴파일하여 실행할 수 있도록 만들어주는 소프트웨어이다.

https://github.com/devFancy/2023-CS-Study/blob/main/java/java_jvm_architecture.md

  1. 자바로 개발된 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당한다.
  2. 자바 컴파일러(Javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일 한다.
  3. Class Loader를 통해 JVM Runtime Data Area로 로딩한다.
  4. Runtime Data Area로 로딩된 .class들은 Execution Engine을 통해 해석한다.
  5. 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어진다.

컴파일이란??

원시코드(소스코드)를 컴퓨터가 이해할 수 있는 목적코드(바이트코드, 기계어)로 바꿔주는 것이다.

목적코드를 실행파일로 바꾸는 것을 링크라고 한다.

빌드(Build)
소스 코드파일을 하나의 실행파일로 만들어주는 과정이다.

https://velog.io/@jjd/%EC%9E%90%EB%B0%94%EC%9D%98-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EA%B3%BC%EC%A0%95

  1. 작성된 소스코드를 자바 컴파일러가 JVM이 이해 할 수 있는 바이트코드로 변환한다.
  2. 컴파일된 바이트 코드를 JVM 내부의 클래스 로더가 가져와 동적 로딩을 통해 JVM 메모리 상에 적재한다.
  3. JVM 메모리에 적재된 바이트코드를 실행엔진을 통해 실행한다.

클래스 로더 시스템

➡️ 기본적으로 자바 프로그램들은 클래스들로 이루어져 있다. IDE에서 프로그래머가 작성한 코드를 컴파일하면 JVM이 읽을 수 잇는 .class 파일이 된다.

➡️ 클래스 로더는 이렇게 생성된 클래스 파일들을 엮어서 JVM이 OS로부터 할당받은 메모리 영역인 Runtime Data Area로 적재하는 역할을 한다.

➡️ 클래스 파일들은 Runtime이 될 때, load(적재), links(연결), initialize(초기화)의 과정을 거치게 된다.

 

메모리

➡️ 런타임 데이터 영역은 JVM 프로그램이 실행이 될 때 OS로부터 할당받은 메모리의 영역이다.

💡 JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역

https://github.com/devFancy/2023-CS-Study/blob/main/java/java_jvm_architecture.md

모든 스레드가 공유해서 사용(GC의 대상)

  • 힙 영역(Heap Area)
  • 메서드 영역(Method Area)

스레드마다 하나씩 생성

  • 스택 영역(Stack Area)
  • PC 레지스터(PC Register)
  • 네이티브 메서드 스택(Native Method Stack)

메서드 영역

➡️ 메서드 영역은 JVM이 시작될 때 생성되는 공간으로 바이트 코드(.class)를 처름 메로리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간이다.

➡️ JVM이 동작하고 클래스가 로드될 때 적재되서 프록램이 종료될 때까지 저장된다.

➡️ 클래스 수준의 정보(클래스 이름, 부모 클래스 이름, 메서드, 변수)를 저장한다.

➡️ 다른 Thread 사이에서 공유되는 자원이다.

Method 영역에 저장하는 데이터
  • Type 정보(Class, Interface, Enum)
  • 메서드와 변수
  • FQCN(Fully Qualified Class Name)
    -> object, 함수, 변수의 계층적 구조를 모두 포함하여 표현하는 것을 말한다.
@SpringBootApplication
public class Apppp {
	public static void main(String[] args) {
    	// FQCN use
    	org.springframework.boot.SpringApplication.run(Appp.class, args);
        
        //FQCN not use
        SpringApplication.run(Appp.class, args);
        
        //in java
        //FQCN use
        String fancy = new String();
        
        //FQCN not use
        java.lang.String fancy = new java.lang.String();
    }
}

 

힙 영역

➡️ new 키워드로 생성된 객체와 배열이 생성되는 영역이다.

➡️ 주기적으로 GC가 제거하는 영역이다.

https://github.com/devFancy/2023-CS-Study/blob/main/java/java_jvm_architecture.md

  • Heap Area는 효율적인 GC를 위해 위와 같이 크게 3가지의 영역으로 나뉘게 된다.
  • Young Generation : 영역은 자바 객체가 생성되자마자 저장되고, 생긴지 얼마 안되는 객체가 저장됨
    Heap 영역에 객체가 생성되며 최초로 Eden 영역에 할당된다. 그리고 이 영역에 데이터가 어느정도 쌓이게 되면 참조정도에 따라 Service의 빈 공간으로 이동되거나 회수된다.
    Young Generation 영역이 차게 되면 참조 정도에 따라 Tenured Generation(Old) 영역으로 이동되거나 회수됨
    Young Generation, Tenured Generation에서 GC를 Minor GC라고 한다.
  • Tenured Generation : Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한번에 삭제한다.
    시간이 오래 걸리는 작업이고 이때 GC를 실행하는 스레드를 제외한 모든 스레드는 작업을 멈추게 됨(Stop-the-World)
    Old영역의 메모리를 회수하는 GC를 Major GC라고 한다.

스택 영역

➡️ 지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역이다.

 

PC 레지스터

➡️ Thread가 생성될 때마다 생성되는 영역으로 프로그램 카운터, 즉 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역.

 

네이티브 메서드 스택
➡️ 자바 이외의 언어(C, C++, 어셈블리 등)로 작성된 네이티브 코드를 실행할 때 사용되는 메모리 영역으로 일반적으로 C 스택 사용

➡️ 보통 C/C++ 등의 코드를 수행하기 위한 스택을 말하며 JNI 자바 컴파일러에 의해 변환된 자바 바이트 코드를 읽고 해석하는 역할을 하는 것이 자바 인터프리터이다.

 

실행 엔진

➡️ 클래스 로더에 의해 JVM으로 로드된 .class 파일들은 Runtime Data Area의 Method Area에 배치되는데 바이트 코드를 실행 엔진에 제공하여 정의된 내용대로 바이트 코드를 실행시킨다.

 

가비지 컬렉터(GC)

https://github.com/devFancy/2023-CS-Study/blob/main/java/java_jvm_architecture.md

  • 자바 가상 머신은 가비지 컬렉터를 이용하여 더는 사용하지 않는 메모리를 자동 회수해 준다.
    Heap 메모리 영역에 생성(적재)된 객체들 중 참조되지 않은 객체들을 탐색 후 제거하는 역할을 한다.
    GC 역할을 수행하는 스레드를 제외한 나머지 모든 스레드들은 일시정지 상태가 된다.

참고 자료 : https://github.com/devSquad-study/2023-CS-Study/tree/main/java

728x90
반응형