JVM에 대해 정리하고자 한다.
- JVM(Java Virtual Machine)은 자바를 실행하기 위한 가상 기계입니다.
자바로 작성된 애플리케이션은 일반적으로 작성된 애플리케이션과 다르게 모두 JVM에서만 실행됩니다.
자바는 운영체제에 독립적인 특징을 가지고 있는데, 그것이 가능한 이유는 JVM에서 실행되기 떄문입니다. Java애플리케이션은 JVM하고만 상호작용을 하기 때문에 다른 OS에서도 프로그램의 변경 없이 실행이 가능합니다 따라서 운영체제에 독립적이라고 할 수 있습니다.
-단 JVM은 운영체제에 종속적이기 떄문에 해당 운영체제에서 실행 가능한 JVM이 필요합니다.
일반 애플리케이션의 코드는 바이너리코드로 컴파일 되어 운영체제만을 거치고 하드웨어로 전달되는 반면에 Java 애플리케이션은 JVM을 한번 더 거치기 때문에, 그리고 바이너리코드로 컴파일된 상태가 아니고 실행시에 해석(interpret) 되기 때문에 속도가 느리다는 단점을 가지고 있습니다.
프로그래밍 언어로 작성된 코드를 실행시키는 방식중 대표적인 두가지로 인터프리터와 컴파일 방식이 있습니다.
컴파일러는 소스코드 전체를 해석한 후, 한번에 실행되는 방식으로 컴파일 이후 생성된 실행 결과물은 실행 속도가 빠릅니다.
인터프리터는 프로그램 실행 시 소스코드의 각 행을 한 줄씩 분석하여 명령을 처리하는 방식으로, 수정이 간다하고 바로 바로 실행이 가능하지만 각 행마다 연속적으로 분석하여 실행하는하기 때문에 속도가 느립니다.
일반적으로 소스파일을 컴파일한 파일을 목적파일이라고 하는데 보통의 언어(C/C++)는 목적파일이 바이너리 코드의 형태를 갖습니다.
자바는 java로 작성된 소스파일(.java)을 자바 컴파일러(javac)를 통해 목적파일(바이트 코드/.class)을 생성 합니다. 이후 바이트코드로 생성된 목적 파일을 JVM을 통해 해석된 후 수행 됩니다.
자바 바이트 코드 : JVM이 이해라 수 있는 코드로 아직 컴퓨터는 읽을 수 없는 반기계어.
따라서 자바는 컴파일러와 인터프리터 모두 해당된다고 할 수 있습니다.
JVM 내로 클래스(.class)를 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다. Runtime 시에 동적으로 클래스를 로딩해주는 역할, 즉 클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링킹한다는 것을 말한다.
메소드 호출시 해당 메소드를 가진 클래스 바이트코드가 로딩된 적이 없다면, JVM은 JRE라이브러리 폴더에서 클래스를 찾고 없다면 CLASSPATH 환경변수에 지정된 폴더에서 클래스를 찾는다.
JVM이 프로그램을 수행하기 위해 운영체제로부터 할당받은 메모리 공간으로 크게 5가지 영역으로 나눌 수 있다.
스레드별 제한되어 공유되는 영역
여러 스레드에서 참조할 수 있는 공유 영역
인터프리터 (interpret) : 자바 바이트 코드를 명령어 단위로 한줄씩 실행합니다. 한줄마다 네이티브 코드로 컴파일하는 것입니다.
JIT 컴파일러 : 인터프리터 단점을 보완하기 위해 도입, 인터프리터 방식으로 실행하다 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 해당 더 이상 인터프리팅 하지 않고 네이티브 코드로 직접 실행하는 방식이다. 인터프리팅하는 것보다 훨씬 오래 걸리므로 해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 기준을 넘을 떄에만 컴파일은 수행합니다. JVM의 핵심으로 JVM 내에서 성능에 가장 큰 영향을 줍니다.
네이티브 코드는 캐시에 보관되기 때문에 컴파일 되었다면 빠르고 수행된다.
Garbage : 유효하지 않는 메모리, 즉 주소를 잃어버려서 사용할 수 없는 메모리를 말한다.
아주 유익한 내용이네요!