JVM(Java Virtual Machine)은 JAVA를 실행하기 위한 가상머신이다.
Java application은 WORA (Write Once Run Anywhere)이라고도 불린다. 이는 한 OS에서 Java 코드가 작성된다면, Java 지원 시스템에서도 조정 없이 실행될 수 있다는 것을 의미한다. 그리고 JVM이 이러한 역할을 수행한다.
즉, JVM은 한 CPU가 한 OS에 의존하지 않고 Java를 인식하고 실행할 수 있도록 하는 가상머신이다.
".java" file은 CPU에 의해 인식될 수 없기 때문에 기계어(machine code)로 compile 되어야 한다.
하지만 Java는 이 JVM 이라는 가상머신을 거쳐서 OS에 도달하기 때문에 OS가 인식할 수 있는 기계어로 바로 컴파일 되는게 아니라 JVM이 인식할 수 있는 Java bytecode(".class" file)로 변환된다.
이렇게 변환된 bytecode 역시 기계어가 아니기 때문에 OS에서 바로 실행할 수 없다. JVM은 OS가 bytecode를 이해할 수 있도록 해석해준다. 이를 통해 bytecode가 특정 OS에 의존하지 않고 JVM 위에서 실행될 수 있게 된다.
JVM은 Class Loader, JVM Memory, Execution Engine 등을 포함하고 있다.
Class Loader은 주로 아래의 세가지 작업을 담당한다.
풀어서 설명하자면, Class Loader은 ".class" file을 JVM에 로딩하고, 이를 링크하여 JVM의 메모리 영역에 배치하는 역할을 담당한다.
Loading: Class loaderd은 “.class” file을 읽고, 그에 상응하는 binary data를 생성하고 method area에 저장한다.
Linking: 로드된 “.class” file을 사용하기 위해 검증하고 준비하는 과정이다.
Symnolic reference
자바에서는 특정 객체를 참조할 때 Memory Address를 직접 참조하는게 아니라, 객체의 이름으로 참조한다. 이렇게 객체의 이름으로 참조하는 것은 Symbolic Reference라고 한다.
Initialization: 링크 과정 후, class file의 code를 읽고 모든 정적 변수에 정의된 값을 할당한다.
프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간으로 컴파일된 bytecode("class" file)이 메모리에 실행가능한 상태로 로드된 공간이다.
1. Method area: 메서드 영역에는 클래스 이름, 상위 클래스 이름, 메서드 및 변수 정보 등 모든 class level 정보가 저장되며, 여기에는 정적 변수도 포함된다. JVM당 메서드 영역은 하나만 존재하며, 이는 공유 자원(shared resource)이다.
2. Heap area: "new" 키워드를 사용하여 생성된 모든 객체의 정보가 힙 영역에 저장된다. 힙영역 역시 JVM당 하나만 존재하고 공유자원이다. 객체를 참조하는 변수나 field가 없다면 garbage collection에 의해 제거된다.
3. Stack area: stack area는 공유자원이 아니다. 각 스레드마다 JVM은 하나의 run-time stack을 생성하고 스택을 이곳에 저장한다. 이 스택의 각 블록은 activation record/stack fram라고 불리고 method의 호출을 저장한다. 해당 메서드의 모든 지역변수는 해당 stack fram에 저장된다. 스레드가 종료되면 해당 스레드의 run-time stack은 JVM에 의해 파괴된다.
4. PC Registers: 스레드의 현재 실행 중인 명령어의 주소를 저장한다. 각 스레드는 별도의 PC 레지스터를 가진다.
5. Native method stacks: 각 스레드마다 별도의 네이티브 스택이 생성된다. 이 스택은 네이티브 메서드 정보를 저장한다.
Execution engine은 "*.class"(bytecode)를 실행한다. Class Loader는 bytecode를 JVM의 Runtime Data Area영역에 배치하고, Execution engine이 이를 실행한다. bytecode를 한 줄씩 읽고, 다양한 메모리 영역에 있는 데이터와 정보를 사용하여 명령을 실행한다.
English version
https://sapphire-beach-570.notion.site/JVM-0ec5cccdb71d4a09a820cf7984c52f14
📁 Reference
https://inpa.tistory.com/entry/JAVA-%E2%98%95-JVM-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD-%EC%8B%AC%ED%99%94%ED%8E%B8
https://imbf.github.io/interview/2021/03/02/NAVER-Practical-Interview-Preparation-4.html