자바가 운영체제에 독립적일 수 있는 이유는 JVM 덕분이다.
개발자가 자바 소스코드(.java)를 작성
자바 컴파일러(Java Compiler)가 자바 소스파일을 컴파일
컴파일된 바이트 코드를 JVM의 클래스로더(Class Loader)에게 전달
클래스 로더는 동적로딩(Dynamic Loading)을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역(Runtime Data area), 즉 JVM의 메모리에 올린다.
클래스 로더 세부 동작
로드 : 클래스 파일을 가져와서 JVM의 메모리에 로드
검증 : 자바 언어 명세(Java Language Specification) 및 JVM 명세에 명시된 대로 구성되어 있는지 검사
준비 : 클래스가 필요로 하는 메모리를 할당 (필드, 메서드, 인터페이스 등등)
분석 : 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경
초기화 : 클래스 변수들을 적절한 값으로 초기화 (static 필드)
실행엔진(Execution Engine)은 JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행한다. 이때, 실행 엔진은 두가지 방식으로 변경
인터프리터
JIT 컴파일러(Just-In-Time Compiler)
Garbage Collector
해석된 바이트 코드는 메모리 영역에 배치되어 실질적인 수행이 이루어지며, 실행 과정 속 JVM은 필요에 따라 스레드 동기화나 가비지 컬렉션 같은 메모리 관리 작업을 수행
Runtime Data Areas
JVM이 운영체제 위에서 실행되면서 할당받는 메모리 영역이며 총 5가지 영역으로 나누어짐
(이 중에 힙과 메서드 영역은 모든 스레드가 공유해서 사용함)
PC 레지스터 : 스레드가 어떤 명령어로 실행되어야 할지 기록하는 부분(JVM 명령의 주소를 가짐)
스택 Area : 지역변수, 매개변수, 메서드 정보, 임시 데이터 등을 저장
네이티브 메서드 스택 : 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역
힙 : 런타임에 동적으로 할당되는 데이터가 저장되는 영역. 객체나 배열 생성이 여기에 해당함
(또한 힙에 할당된 데이터들은 가비지컬렉터의 대상이 됨. JVM 성능 이슈에서 가장 많이 언급되는 공간임)
메서드 영역 : JVM이 시작될 때 생성되고, JVM이 읽은 각각의 클래스와 인터페이스에 대한 런타임 상수 풀, 필드 및 메서드 코드, 정적 변수, 메서드의 바이트 코드 등을 보관함
출처
링크