Java Virtual Machine으로, 자바 가상 기계
🤔 C/C++처럼 크로스 컴파일(타겟 플랫폼에 맟춰서 컴파일하는 것)해서 배포하면 되지 않을까?
클래스로더가 자바 바이트코드를 런타임 데이터 영역에 로드하고, 실행 엔진이 자바 바이트를 실행한다.
클래스로더 작업은 런타임시 처음으로 클래스를 참조할 때 발생한다. 클래스 로드를 요청받으면, 클래스 로더 캐시 > 상위 클래스 로더 > 자기 자신 순으로 해당 클래스가 있는지 확인한다. 만약 클래스로더가 아직 로드되지 못한 클래스를 발견하면, (로드-링크-초기화)한다.
+) 로드 / 링크/ 초기화 자세히 알아보기
<로드> : 클래스를 파일에서 가져와서 JVM 메모리에 로드한다. 로딩은 특정 이름을 가진 클래스 또는 인터페이스 유형의 이진 표현을 찾고(finding) 해당 이진 표현에서 클래스 또는 인터페이스를 만드는(creating) 프로세스이다.
<링크> : 연결은 클래스 또는 인터페이스를 가져와 이들의 유형과 다이렉트 수퍼 클래스와 수퍼 인터페이스를 검사하고 준비하는 프로세스이다.
<초기화> : 클래스 변수들을 적절한 값으로 초기화한다. static initializer들을 수행하고, static 필드들을 설정된 값으로 초기화한다.
런타임 데이터 영역은 JVM이 운영체제 위에서 실행되면서 할당받는 메모리 영역이다. 이 영역은 크게 5가지로 나뉜다.
모든 스레드가 공유하는 영역
스레드마다 하나씩 생성되는 영역
📑 스택 프레임이란?
- JVM 내에서 메서드가 수행될 때마다 하나의 스택 프레임이 생성되어 해당 스레드의 JVM스택에 추가되고 메서드가 종료되면 스택 프레임이 제거된다.
- 각 스택 프레임은 지역 변수 배열(Local Variable Array), 피연산자 스택(Operand Stack), 현재 실행 중인 메서드가 속한 클래스의 런타임 상수 풀에 대한 레퍼런스를 갖는다.
실행엔진에서는 바이트코드를 실행한다. 이때 바이트코드의 명령어는 1바이트의 OpCode와 추가 피연산자로 이루어지고, 실행 엔진은 하나의 OpCode를 가져와 피연산자와 함께 작업한 후, 그 다음 OpCode를 수행하는 식으로 동작한다.
바이트코드는 JVM은 이해할 수 있지만 아직 기계가 이해할 수 없는 코드다. 따라서 실행 엔진은 바이트코드를 기계가 실행할 수 있는 코드로 변환한다. 변환 방식에는 2가지가 존재한다.
프로그램이 실행되면, JVM은 OS로부터 이 프로그램이 필요로하는 메모리를 할당받음. JVM은 할당받은 메모리를 용도에 따라서 여러 영역으로 나누어 관리함.
자바 컴파일러(JAVAC)가 자바 소스코드를 읽고, 자바 바이트코드(.class)로 변환시킴.
변경된 class파일들은 클래스 로더를 통해 JVM메모리 영역으로 로딩함.
로딩된 class파일들은 실행엔진(Execution engine)을 통해 해석됨.
해석된 바이트코드는 메모리 영역에 배치되어 실질적인 수행이 이루어짐. 이러한 실행과정 속 JVM은 필요에 따라 스레드 동기화나 가비지 컬렉션 같은 메모리 관리 작업도 수행함.