Java가 실행되기까지
- java 애플리케이션을 실행하면
JVM은 OS로부터 메모리를 할당한다.
자바 컴파일러 (javac) 가 자바 소스코드 (Xxx.java) 를 바이트코드 (Xxx.class) 로 컴파일 한다.
클래스 로더 (Class Loader) 를 통해 JVM 메모리 (Runtime Data Areas) 로 로딩한다.
- 로드된 클래스 파일 (Xxx.class) 들은 기계가 읽을 수 없으므로
실행 엔진 (Execution Engine) 을 통해 기계어로 변환하여 실행한다.
- 이 과정에서
실행 엔진에 의해 가비지 콜렉터 (Garbage Collector) 등도 작동된다.
- 자바 어플리케이션이 실행되면
JVM은 시스템으로부터 필요한 메모리를 할당받고, 용도에 따라 여러 영역으로 나누어 관리한다.
- 메소드 영역 (Method Area)
- JVM 이 클래스 파일 (*.class) 을 읽어 클래스 데이터를 저장하는 영역이다. 이때 클래스 변수도 함께 생성된다.
- 힙 (Heap)
- 인스턴스가 생성되는 공간이다. 프로그램 실행 중 new 연산으로 생성되는 인스턴스 변수들이 생성된다.
- 호출 스택 (Call Stack)
- 메소드의 작업에 필요한 메모리 공간을 제공한다. 메소드가 호출되면 호출 스택에 메모리가 할당되고 해당 메소드가 수행되는 동안 필요한 값 등을 저장하는데 사용된다. 메소드 실행이 완료되면 할당되었던 메모리 공간은 반환된다.
자세히 보는 JVM 구동 방식

사진 출처: https://inpa.tistory.com/entry/JAVA-☕-그림으로-보는-자바-코드의-메모리-영역스택-힙
Class Loader
- JVM으로 바이트 코드(.class) 로드 → 링크를 통해 배치
- 어플리케이션에서 필요한 경우 동적으로 메모리에 적재
Runtime Data Area
- Method
- static 변수
- 클래스 레벨의 모든 데이터
- 상수
- Runtime Constant Pool이라는 별도의 영역
- 저장되는 정보
- Field Info: 멤버 변수명, 데이터 타입, 접근 제어자의 정보
- Method Info: 메소드명, 리턴 타입, 매개변수, 접근 제어자의 정보
- Type Info: Class인지 Interface인지 여부, Type의 속성, 이름, Super Class의 이름
- GC 관리 대상
- 여러 스레드 간 공유
- Heap
- 객체
- new 연산자로 생성된 모든 객체, 인스턴스 변수, 배열
- GC 관리 대상
- 여러 스레드 간 공유
- Stack
- 변수, 임시 데이터, 스레드/메소드 정보
- 역할 종료 시 즉시 소멸
- PC(Program Counter) Register
- 스레드 시작 시 생성
- 스레드가 로직을 처리하면서 계속 갱신
- 각 스레드 별로 생성
- 현재 실행 중인 상태 정보 저장
- 어떤 명령을 실행해야 할지 기록
- 현재 수행 중인 부분의 주소를 가리킴
- Native Method Stack
- 기계어 프로그램 실행
- Java Native Interface를 통해 바이트 코드로 변환하여 저장
- 각 스레드 별로 생성
Execution Engine
- Runtime Data Area에 할당된 바이트 코드를 실행시키는 주체
- 인터프리터
- 바이트 코드 해석 및 실행
- 같은 메소드라도 여러 번 호출 시 매번 새로 수행
- JIT(Just In Time) 컴파일러
- 인터프리터 단점 개선, 반복되는 코드 발견
- 전체 바이트코드 컴파일 → Native Code(C, C++, 어셈블리어)
- 가비지 콜렉터
- 더 이상 참조되지 않는 메모리 객체 제거
- 기본적으로 자동 실행
- Stop The World
- GC가 수행되기 위해 JVM이 멈추는 현상
- GC 관련 스레드 이외의 모든 스레드는 멈춤
- 이 시간을 최소화 = 튜닝
- 수동 실행 방법:
System.gc()