JVM은 무엇인가? java 코드는 어떻게 실행되는가?
JVM이란 무엇인가?
- JVM은 Java Virtual Machine의 준말로 자바의 코드를 컴퓨터가 이해할 수 있는 언어로 바꿔주는 가상 머신이다. 자바가 현재 C와 더불어 가장 많이 활용된 이유는 JVM에 의해서다.
- JVM으로 인하여 자바 코드는 어떤 OS에서도 동작한다. 이러한 특징 덕분에 2000년대 이후 프로그래밍 언어의 대세를 차지할 수 있었다. 자바의 이식성은 자바의 가장 중요한 특징이다.
- JVM의 장점은 아직도 유효하다. 개발 언어로서 자바가 힘을 잃는다 하더라도 JVM 기반의 언어는 계속 유지될 것이다. 현재 널리 사용 중인 코틀린과 스칼라는 JVM을 기반으로 작동한다. 안드로이드는 JVM과 유사한 구조의 안드로이드 컴파일러를 통해 동작한다.
컴파일 - JVM으로 읽을 수 있는 바이트 코드로 변환하기
흐름 |
---|
자바소스파일(.java) |
↓ |
컴파일(javac.exe) |
↓ |
바이트 코드 파일(.class) |
↓ |
JVM 구동 |
컴파일과 바이트 코드
- 자바소스파일(.java)은 사람이 이해할 수 있는 언어로서 개발자가 직접 작성하는 코드이다.
- 컴파일러를 사용하여 자바소스파일을 바이트코드 파일로 변환한다.
- 바이트 코드는 JVM이 이해할 수 있는 언어(기계어)이다. 자바와 코틀린이 동일해지는 순간은 바로 바이트코드로 변환한 결과물로서 컴파일 데이타(바이트코드)이다.
런타임 - JVM의 작동
<출처 : https://en.wikipedia.org/wiki/Java_virtual_machine>
JVM을 작동시키는 프로그램 - JRE / JDK
- JVM은 바이트코드를 컴퓨터 프로그램으로서 동작시킨다. 이러한 행위 혹은 시점을 런타임이라 한다.
- JVM은 JRE 혹은 JDK를 통해 동작한다.
- JRE는 Java Runtime Enviroment의 준말로 JVM을 작동시키기 위한 최소한의 기능을 가지고 있다.
- JDK는 JRE를 포함하는 개념이다. 자바 개발을 위한 다양한 라이브러리, 서버 기능 등을 가지고 있다. 개발 시 JDK를 사용한다.
- JDK는 다양한 회사에서 개발 및 배포 중이다.
- 오라클은 자바의 저작권을 가지고 있다. 오라클은 Oracle JDK와 OpenJDK 두 개의 JDK를 제공한다.
- 구글과 논쟁이 있었지면 결과적으로 JAVA언어 자체는 무료이다. 오라클이 제공하는 OpenJDK 또한 무료이다. 오라클 이외의 다양한 회사에서 제공하는 JDK 역시 대부분 무료다.
- Oracle JDK은 부분적으로 유로이다. Non-General Purpose Computing에 대해서만 라이센스 구독비를 받는다.
- 웹 개발자 입장에서 자바 개발자 입장에서 자바의 유료화로 인하여 개발이 불가능한 상황은 없다고 볼 수 있다.
- 자바 유료화에 대한 참고할만한 내용 - https://www.lpcinc.co.kr/blog/java-%EC%9C%A0%EB%A3%8C-%EB%85%BC%EC%9F%81-oracle-jdk%EC%99%80-openjdk%EC%9D%98-%EC%B0%A8%EC%9D%B4-%EC%A0%95%EB%A6%AC
JVM의 세 영역
- JVM은 Class Loader, Runtime Data Area, Execution Engine으로 나뉘어 진다.
Class Loader
- 런타임에 필요로 하는 초기화 작업을 수행한다.
- 클래스 파일(바이트코드)을 읽고 메모리(JVM Memory, Runtime Data Area)에 로드한다.
Runtime Data Area
- Execution Engine는 Runtime Data Area에 적재된 메모를 읽고 프로그램을 동작시킨다.
Execution Engine
인터프리터와 Jit Compiler
- 자바는 컴파일 언어이자 인터프리터 언어이다. 자바소스파일에서 바이트코드를 변환할 때는 컴파일한다. 하지만 컴파일된 바이트코드를 컴퓨터는 이해할 수 없다. JVM은 바이트코드를 컴퓨터가 이해할 수 있는 바이너리코드로 실시간 번역하는 업무를 수행한다. 바이트 코드를 실시간으로 읽고 번역하는 행위를 인터프리터라 한다.
- Jit Compiler는 JVM의 인터프리터 과정에 중요한 역할을 담당한다. 바이너리 코드의 번역 과정에서 jit은 중복되는 내용을 캐싱하여 런타임의 효율성을 증대시키는 기능을 내장한다.
- 자바 언어의 성능 증대는 jit의 발전과 함께 한다. JDK의 성능이 높아지면 jit의 성능도 함께 좋아진다.
- 참고로 jit은 Just In Time, 실시간이란 의미이다.
Garbage Collector
- 자바의 중요한 특징 중 하나는 가비지 컬렉터이다. 개발자는 메모리 관리를 하지 않고 가지비 컬렉터에 위임한다.
- 개발자는 가비지 컬렉터를 통제할 수단을 아주 제한적으로 가지지만 그 권한의 행사를 권장하지 않는다.
- 이러한 특징 덕분에 자바 개발의 편의성이 증대된다.
컴파일 에러와 런타임 에러
- 컴파일 과정에서 발생한 에러와 런타임 시점에서 발생한 에러를 구분할 수 있다. 전자는 컴파일 에러이며 후자는 런타임 에러이다.
- 컴파일 에러의 경우 일종의 문법 오류이다. java파일에서 class파일로의 변환 자체가 불가능하다.
- 컴파일 에러는 런타임 에러에 대비하여 분명하고 직관적이다. 해결이 단순하다.
- 런타임 에러의 경우 어플리케이션이 돌아가는 도중에 알 수 있다. 보통 로그 메시지를 기반으로 역추적 해야 한다. 클라이언트가 사용하는 과정에서 경험하므로 서비스 제공자에 대한 신뢰의 문제와 직결된다. 매우 위험한 문제다.
- 개발 과정에서 런타임 오류가 발생할 가능성을 최소화해야 한다.
UnsupportedClassVersionError과 컴파일러 버전 에러
- 클래스 파일을 컴파일한 버전이나 옵션에 따라, 해당 파일을 읽을 수 있는 컴파일러가 결정된다.
- 사용할 수 없는 컴파일러로 읽을 때 UnsupportedClassVersionError 에러가 발생한다.