Java Virtual Machine (자바 가상 머신)
- 자바 기반 애플리케이션의 실행 환경 제공
사용자 언어로 작성된 프로그램이 실행되기 위한 흐름에 대한 이해가 필요하다
- 결국 사용자가 작성한 프로그램이 실행되기 위해서는 OS와의 통신이 필요하다.
- 기계어로 변환된 코드가 사용자 영역에서 커널 영역 사이의 시스템 콜 기반으로 통신이 되어야 한다.
여기서 중요한 점은 OS의 종류가 다르다면(Window , Mac) 제공하는 시스템 콜의 종류도 다르고 결국 언어마다 OS에 대한 종속성이 존재할 수 있다.
Java 언어의 가장 큰 특징은 ‘OS에 종속적이지 않다’ 라는 것이다. 이것이 가능한 이유는 Java 언어가 실행되는 환경인 JVM 때문인 것이다.
- JVM은 자체적인 Java 언어의 실행 환경을 제공하고 JVM이 OS의 커널 영역과 통신한다. 이러한 이유 때문에 JVM만 설치되어 있다면 OS에 상관없이 Java 언어를 실행시킬 수 있다.
Java 언어는 OS에 종속적이지 않는 실행이 가능하다. 하지만 결국 OS단과 통신하는 중간 매개체로서 JVM이 존재한다. 결국 JVM은 OS에 종속적이라는 것이다.
Java 언어로 작성된 코드 ( 우리가 흔히 자바 소스 코드라 부르는 파일이다.)
- 모든 언어로 작성된 코드가 그렇듯 CPU가 이해하기 위해서는 기계어로 변환되어야 한다.
- 하지만 JVM이 OS와의 통신을 담당하기 때문에 결국 자바 소스 코드는 JVM이 이해하기 위한 형태로 변환되어야 한다.
런타임 시 처음으로 클래스를 참조할 때 해당 클래스를 로드하고 JVM 메모리 영역에 배치
- Runtime 시 클래스의 동적 로드를 담당
- 클래스의 인스턴스화를 수행하는 곳
JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 실행하는 역할
- 명령어를 실행하는 방식에는 인터프리터 방식과 JIT 컴파일러 방식이 있다.
바이트 코드 명령어를 하나씩 읽어서 해석하고 실행합니다. 하나하나의 실행은 빠르나, 전체적인 실행 속도가 느리다는 단점을 가집니다.
바이트 코드 전체를 컴파일하여 바이너리 코드로 변경하고 이후에는 해당 메서드를 더이상 인터프리팅 하지 않고, 바이너리 코드로 직접 실행하는 방식
JIT는 바이트 코드를 어셈블러 같은 네이티브 코드로 바꿈으로써 실행이 빠르지만 역시 변환하는데 비용이 발생
Java언어의 특징으로 ‘동적 로딩을 지원한다’가 있는데 이는 Class Loader를 통해 가능한 것이다.
- 동적 로딩
- 실행 시 모든 클래스가 로딩되지 않고 필요한 시점에 클래스를 로딩하여 사용
- JVM의 Method 영역에 클래스를 동적으로 Load 하는 것
클래스 로더에서 Java class 파일의 정보를 Method 영역으로 Load하는데 있어 3가지 단계를 거치게 된다. (로딩 → 링크 → 초기화)
.class 파일을 Binary Code로 변환하여 Method 영역에 저장
- 로딩 후에 해당 클래스 타입의 객체를 생성하여 Heap Area에 저장
- Method 영역에 저장되는 정보
- 클래스 파일과 Class, Interface, Enum의 관련 여부
- 변수나 메서드 정보
코드 내부의 레퍼런스를 연결
- Verify
- .clsss 파일 형식의 유효성 검사
- Prepare
- 클래스가 필요한 메모리 할당 + 데이터 구조 준비
- Resolve
- 심볼릭 메모리 레퍼런스를 메서드 영역에 있는 실제 레퍼런스로 변환
참조 관계의 클래스에 대해 메모리 주소를 기반으로 참조 관계를 구성하는 것이 아닌 참조하는 클래스의 이름으로 레퍼런스 관계가 지정되어 있다.
Static 변수를 초기화하고 값을 할당하는 과정
class 로딩 과정에 있어 자신의 부모 class loader에게 로딩을 위임하는 방식
자바의 기본 라이브러리 및 자바 가상 머신 자체를 포함
표준 확장 폴더에서 클래스를 로드
사용자가 정의한 클래스 및 외부 라이브러리들이 위치한 곳
하나의 클래스를 로딩하는 과정에서 동적으로 다른 클래스 파일을 로드하는 것
코드를 실행하는 순간 클래스를 로딩하는 것 ( Class.forName() )