JVM ( Java Virtual Machine )
- 자바 가상머신으로 자바 바이트코드(.class)를 실행 코드로 변환하여 실행한다.
- 바이트 코드를 JIT or 인터프리터로 실행을 해서 OS에 맞는 기계어로 변환되서 실행한다.
- JVM Specification
- JVM은 홀로 배포되지 않고 JRE (Java Runtime Environment) 형식으로 배포된다
JRE (Java Runtime Environment)
- JRE는 자바 애플리케이션을 싱행할 수 있도록 구성된 배포판을 말한다
- 개발 관련 도구 (JDK)는 포함하지 않는다
- JVM과 핵심 라이브러리 및 자바 런타임 환경에서 사용하는 프로퍼티 세팅이나 리소스 파일을 가지고 있다
JDK ( Java Development Kit )
- Java 11부터는 JDK만 지원한다
- JRE + 개발 툴
- JDK로 주로 개발한다.
자바 유료화?
- 오라클에서 만든 Oracle JDK 11 버전부터 상용으로 사용할 때 유료
- 예) 오라클에서 만든 Oracle Open JDK 11은 무료
예) Amazon Corretto Open JDK 11은 무료
JVM 언어
최초의 JVM은 Java만 지원하도록 만들어졌지만 결국에 필요한건 .class 파일이다.
즉 다른 프로그래밍 언어로 코딩을 하더라도 컴파일 했을 때 .class 파일이 만들어진다면 JVM이 실행할 수 있다
JVM의 Spec을 활용하는게 가능하다
예) Kotlin으로 작성을 하고 컴파일하면 .class 파일이 나온다.
JAR ( Java Archive)
- JAR는 여러개의 자바 클래스 파일과 클래스들이 이용하는 관련 리소스 및 메타 데이터를 하나의 파이롤 모아서 자바 플랫폼에 응용 소프트웨어나 라이브러리를 배포하기 위한 소프트웨어다.
- JAR 파일은 ZIP 파일 포맷으로 압축된 파일형태
- Jar 명령을 통해서 압축을 풀거나 JAR 파일 만드는게 가능하다.
- JAR 파일은 자바 런타임이 효율적으로 어플리케이션을 배치할 수 있는 수단으로 설계되었다.
- 클래스와 관련 리소스들을 단일 파일로 묶어 한 차례의 요청으로 어플리케이션을 다운로드 할 수 있다
JVM 구조
크게 4가지 컴포넌트로 구성된다
- 클래스 로더 시스템
- 메모리
- 실행 엔진
- 네이티브 메소드 인터페이스, 라이브러리
클래스 로더 시스템
- 하는 일은 크게 로딩 ( loading), 링크 ( linking ) 초기화 ( Initialization )으로 구성된다
- 로딩 -> 링크 -> 초기화 순으로 진행한다.
- 자바 바이트 코드를 읽어들여서 메모리에 배치하는게 로딩이 하는 일이다
- 이 때 메모리의 메소드 영역에 저장한다
- 로딩이 끝나면 해당 클래스 타입의 Class 객체를 생성해 힙 영역에 저장한다.
- 링크는 Verify, Prepare, Resolve 세 단계로 나눠져 있다.
- Verify: 클래스 파일 형식이 유효한지 검사한다. (임의로 조작했는지 검사한다)
- Preparation: 클래스 변수(Static 변수)와 기본값에 필요한 메모리를 준비한다
- Resolve: 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
- 어떤 객체가 다른 객체를 참조할 때 실제 레퍼런스가 아니라 논리적인 레퍼런스다.
하지만 Resolve 과정을 넣으면 실제 Heap에 있는 레퍼런스를 가리키도록 할 수 있다.
- 초기화는 클래스에 있는 static한 변수들을 초기화 한다.
메모리
- 메모리는 크게 5가지 컴포넌트로 구성된다
- 스택 ( Stack )
- PC ( PC Registers )
- 네이티브 메소드 스택 ( Native Method Stack )
- 힙 ( Heap )
- 메소드 ( Method )
- 메소드 영역에는 클래스 수준의 정보를 저장한다
- 클래스 이름
- 패키지 경로
- 부모 클래스 이름 ( 상속받은 클래스 )
- class.getSuperClass()로 조회가능
- 메소드 이름
- 변수 이름
- 힙 영역에는 객체를 저장한다
- 나머지 Stack, PC, Native Method Stack 들은 Thread에 국한된다.
- 어떤 Thread인지에 따라 공유하는 자원이 다르다.
- Stack 영역은 Thread 마다 Runtime Stack을 만들고 그 안에다 Stack Frame을 만든다.
- Stack Frame을 통해 어떤 메소드들이 실행 되었는지 확인할 수 있다.
- PC (Program Counter ) 영역은 Thread 마다 현재 어느 위치를 실행하고 있는지 가르켜준다.
- Native Method Stack은 Thread 마다 Native Method를 실행할 때 마다 쌓인다.
- Native Method는 native keyword가 붙어 있고 자바로 구현된 게 아니라 C와 C++로 구현되어 있다.
실행 엔진
- 구성요소는 인터프리터, JIT 컴파일러, GC ( Garbage Collector )가 있다.
- 바이트 코드를 인터프리터가 한 줄씩 실행한다.
- 반복되는 코드는 JIT 컴파일러를 통해 모두 네이티브 코드로 바꿔서 인터프리터의 효율을 높인다.
- GC는 더이상 참조되지 않는 객체를 모아서 정리한다.
- 자바 성능에 관심이 많다면 GC에 대해서 공부를 해야한다.