JVM
Java code나 어플리케이션을 실행하기위한 런타임 환경을 제공한다. Java bytecode를 machine language로 변환한다. JVM은 JRE(Java Run Environment)의 일부이다.
JVM 작동방식
먼저 Java code가 bytecode로 컴파일된다. 이 바이트 코드는 다른 머신에서 해석된다. 바이트코드는 소스코드와 호스트 시스템을 연결하는 언어이다.
JVM Architecture
1. ClassLoader
class 파일들을 로딩하는데 사용되는 시스템이다. Loading,Linking,Initialization을 담당한다.
2. Method Area
필드 정보, 메소드 정보(메소드 이름, 접근 제어자, 리턴 타입), 타입 정보, 상수 runtime pool, 메소드 코드를 저장한다.
3. Heap
모든객체들, 관련된 인스턴스 변수 그리고 배열들이 저장된다. 이 공간은 스레드들간에 공유된다.
4. JVM Language Stack
로컬 변수들을 저장한다, 중간 결과들 또한 저장한다. 각 스레드는 자신만의 JVM stack을 가지고 있다. 함수가 호출될때마다 새로운 프레임이 생성되고 함수호출이 끝나면 삭제된다.
5. PC Register
현재 실행중인 인스트럭션 주소를 저장한다. 각 스레드는 독립적인 PC register를 소유한다.
6. Native Method Stack
다른 언어로 작성된 네이티브 코드에 대한 인스트럭션이 저장된다.
7. Execution Engine
Interpreter와 JIT(Just In time) 컴파일러, GC로 구성이 되는데 Interpreter는 바이트코드를 한줄한줄 해석해서 실행한다. JIT는 자주 실행되는 byte code들을 compile해서 native code로 변환한다.
8. Native Method interface
JVM에서 동작중인 Java code가 라이브러리와 네이티브 어플리케이션을 호출할수 있도록 하는 프레임워크이다.
9. Native Method Library
Execution engine에 필요한 C와 같은 네이티브 라이브러리를 말한다.
코드 컴파일.실행 과정
- Compiler - high language로 작성된 프로그램을 네이티브 코드로 변환
- Linker - 여러 프로그램 파일들을 함께 묶어줌
- Loader - secondary storage(HDD)에 있는 파일들을 RAM에 로드함.
- Execution - OS와 프로세서에 의해서 실행됨.
자바 코드 컴파일.실행 과정
C와는 달리 Linking 과정이 발생하지 않는다. JVM이 RAM에 위치해있고, 실행동안 클래스로더가 클래스파일들을 RAM으로 로드한다. 이 과정에서 byte 코드가 보안상 문제가 없는지 검증된다.
그리고 execution engine이 바이트코드를 native machine code로 변환한다. 이 과정은 두가지 방식으로 발생한다.
1. JIT가 bytecode를 native code로 변환
이것을 just in time compiling이라 부른다. 자바가 C에 비해 느린이유이기도 하다. 한번 실행시킨 코드는 캐시에 저장되어 빠르게 실행시킬 수 있다는 장점이 있다.
JIT는 JVM의 일부이며 bytecode를 해석한다.
2. Interpretter가 byte code를 한줄 한줄 읽어서 native code로 변환한다.
JIT가 모든 bytecode를 native code로 변환하는 것은 비용이 소모 때문에, Interpreter가 byte code를 변환하다가 일정 기준이 지나면 JIT가 동작한다.
자바가 컴파일언어이면서 인터프리터 언어인 이유?
컴파일러언어인 이유는 자바 코드가 바이트코드로 변환되기 때문이다.
인터프리터 인어인 이유는 JIT,Interpreter가 바이트코드를 네이티브 머신코드로 변환하기 때문이다.
Java가 느린이유
- Dynamic Linking : C와 달리, linking이 런타임에 일어난다.
- Run-time interpreter : 바이트 코드를 네이티브 머신 코드로 변환되는 과정이 런타임에 일어난다.