JAVA는 컴파일과 인터프리터 2개의 방식을 혼합하여 코드를 실행하는 특이한 구조를 가지고 있다.
따라서, JAVA 코드 실행 과정을 이해하기 위해서는 컴파일과 인터프리터가 무엇인지 알아볼 필요가 있다
컴파일 | 인터프리터 | |
---|---|---|
해석 방식 | 소스 코드 전체를 한 번에 번역한 뒤 실행 프로그램을 활용해 실행 | 소스 코드를 1줄 단위로 번역하여 실행 |
대표 언어 | C언어 | Python |
장점 | 실행 속도가 빠름 | OS에 자유로움 |
단점 | OS(플랫폼)에 종속적이므로 OS에 맞는 코드를 짜줘야 함 | 실행 속도가 빠름 |
바이트코드는 Java Compiler가 생성하는 코드로써 직접 실행할 수 있는 기계어가 아니라 자바 가상머신(JVM)에 의해 해석될 수 있는 중간 코드 개념이다.
JAVA의 특징 중 하나는 플랫폼에 종속적이지 않는 높은 이식성이였으며, 이를 가능하게 하는 것이 JVM이다.
JVM은 JAVA Bytecode를 해석하여 OS에서 실행할 수 있도록 번역해주는 역할을 수행하는데, 인터프리터 과정에서 OS에 독립적일 수 있게 해주는 공신이 된다.
JVM은 JAVA Virtual Machine의 약자로써, 자바 가상 머신이라는 의미를 가진다.
가상 머신은 프로그램을 실행하기 위해 물리적 머신과 유사한 구조를 소프트웨어를 통해 구현 할 수 있게 해주는 Software를 의미한다.
VirtualBox를 생각해보면 쉬운데, 실제로 Linux OS 컴퓨터를 가진 것은 아니지만 가상 머신을 활용해 설정을 해주면 마치 Linux OS 물리적 머신을 가진 것처럼 활용할 수 있게 되며, 이런 환경을 만들어주는 VirtaulBox라는 Software가 가상머신이 되는 것이다.
JAVA는 가장 먼저 가상 머신이라는 개념을 성공적으로 활용한 프로젝트라고 할 수 있겠으며, 이런 장점을 따라하여 많은 JVM 기반 언어들도 유행하고 있다.(Kotlin, Scala, Groovy 등)
JVM의 역할은 JAVA Application을 Class Loader를 통해 읽고 자바 API와 함께 실행하는 것이다.
즉, 컴파일 결과로 만들어진 '.class' JAVA ByteCode 파일을 읽고 메모리에 배치시켜 자바가 가지고 있는 라이브러리와 연동하여 코드를 실행시키는 주체라고 이해하면 될 것이다.
또한 JVM은 위에서 말했듯 JAVA와 OS 사이 중재자 역할을 수행하여 OS에 독립적으로 코드가 수행될 수 있도록 도와주는 역할도 한다.
가장 중요한 메모리 관리(Garbage Collection)도 JVM에서 수행된다.
항상 C언어나 JVM의 Stack 구조 등을 보면 생각나는 이유가 있다.
굳이 이걸 알아야 할까? 왜 알아야 할까?
솔직히 내 개인적인 생각에는 필수적으로 알아야 하는 개념은 아니라고 생각한다.
하지만 만약 메모리 용량이 부족한 상황이라면 이런 개념은 큰 힘이 될 것이다.
JVM을 알게 된다면 한정된 메모리를 최대한 효율적으로 활용할 수 있어 최고의 성능을 낼 수 있게 된다.
또한 메모리 부족 현상이 발생했거나 메모리 관리가 제대로 되어 있지 않다면 속도 저하 현상이나 튕김 현상 등이 일어날 수 있는데 이런 문제에 대한 발생 확률을 줄이도록 처음부터 효율적인 코딩이 가능해 질 수도 있을 것이다.
최근 HW의 발전으로 메모리 부족 및 메모리 관리의 필요성이 그렇게 크다고 생각이 들지는 않지만, 알아둬서 나쁠 점은 없는 것이다.
프로그램이 실행되면 JVM은 OS로부터 필요한 메모리를 할당받고, JVM은 할당받은 메모리를 용도에 따라 여러 영역으로 나누어 관리한다
자바 컴파일러(javac.exe)가 JAVA SourceCode(.java 파일)을 읽어 들여 JAVA ByteCode(.class)로 변환시킨다.
Class Loader를 통해 '.class' 파일들을 JVM으로 로딩한다.
로딩된 '.class' 파일들은 JVM 내에 존재하는 Execution Engine을 통해 해석된다.
해석된 코드는 JVM 내에 존재하는 Runtime Data Areas에 배치되어 실질적인 수행이 이루어진다
결국 JVM 구조를 알아야 위 과정을 잘 이해할 수 있을 것이다.
따라서, 다음 Section에서 JVM 구조를 잘 뜯어보고, 다시 어려운 버전의 실행 과정을 이해해보자