1. JVM이란 무엇인가?
A Java virtual machine (JVM) is a virtual machine that enables a computer to run Java programs as well as programs written in other languages that are also compiled to Java bytecode. - wikipedia
자바 가상 머신은 컴퓨터가 자바 프로그램을 실행할 수 있도록 도와준다.
Q. JVM은 왜 필요한 것 일까?
A. 기계어는 하나의 언어가 아니기 때문이다.
컴퓨터, 정확히 말하자면 CPU가 이해할 수 있는 언어 기계어는 하나의 언어가 아니다.
CPU 제조사마다 다르기에 특정 프로그램 A를 X, Y, Z라는 각각 다른 컴퓨터 환경에서 실행하려면 각각의 제조사에 맞는 기계어를 알고 있어야 한다.
Q. 그렇다면 개발자는 모든 종류의 CPU에 맞는 기계어 패턴을 알고 있어야 할까?
하드웨어 엔지니어가 아닌 이상 일반적인 소프트웨어 엔지니어의 목표는 요구 사항을 충족하는 프로그램을 개발하는 것이다.
CPU 제조사마다 다른 기계어 패턴을 알 필요 없이 요구 사항을 충족하는 프로그램을 하나의 고급 언어로 작성하는 것이 이상적일 것이다.
자바 가상 머신이란 컴퓨터가 자바 프로그램을 실행할 수 있도록 도와준다.
결국 JVM은 자바 프로그램(바이트 코드)을 다양한 CPU 환경에서 이식성 문제없이 실행할 수 있도록 도와주는 가상 머신
2. 컴파일 하는 방법
자바 소스를 컴파일 및 실행하기 위해서는 기본적으로 아래의 두 프로그램이 필요하다.
javac.exe
java.exe
javac.exe는 자바 소스코드를 컴파일할 때 사용하는 프로그램이며 컴파일된 바이트 코드를 실행할 때 java.exe 사용
또한 javac.exe는 JDK, java.exe는 JRE에 포함되어 있기에 JDK과 JRE를 설치해야 하지만 과거와 다르게 요즘은 JDK에 JRE가 포함된 형태로 배포되고 있기에 JDK만 설치해도 무관
3. 실행하는 방법
java.exe 파일을 사용하여 바이트코드로 컴파일 된 .class 실행
단, 실행 시에는 소스 파일명의 확장자는 붙이지 않음
Q. java compile option
>
4. 바이트코드란 무엇인가
바이너리 코드
|
바이트코드
|
0과 1로 구성되어 있는 코드
C언어로 작성 된 .c 파일을 컴파일한 .obj 파일이 바이너리 코드
하지만 .obj 파일만으로는 실제 컴퓨터가 이해하여 실행할 수 없다. 이때 필요한 것이 링커로 링커는 여러 개의 코드와 데이터를 모아서 연결하여 메모리에서 실행 가능 한 파일로 만드는 역할을 한다.
위 과정이 모두 진행된 후 생성되는 실행 파일이 컴퓨터가 이해 할 수 있는 기계어로 구성
|
0과 1로 구성되어 있는 이진 코드이지만 바이너리 코드와 다르게 가상 머신이 이해할 수 있는 코드
사람에게 더 친숙한 고급언어보다는 덜 추상적이지만 기계어보다는 추상적이다.
컴퓨터가 이해 할 수 있는 기계어로 만들기 위해서는 인터프리터의 도움이 필요하다.
|
5. JIT(짓) 컴파일러란 무엇이며 어떻게 동작하는지
일반적으로 인터프리터 언어(python)보다는 정적 컴파일 언어(C)가 실행 속도가 더 빠르다고들 한다.
Q. why??
그 이유는 JIT 컴파일러의 목적을 보면 알 수 있다.
정적 컴파일 언어의 경우 컴파일에 시간이 오래 걸리는 반면 컴파일 후 결과물(.exe)은 CPU가 이해할 수 있는 '기계어'이기 때문에 실시간으로 번역하여 실행하는 인터프리터 언어보다 빠를 수 밖에 없다.
Java는 컴파일 언어이지만 동적 컴파일 언어이다.
CPU가 이해할 수 있는 기계언어가 아닌 JVM이 이해 할 수 있는 바이트 언어로 컴파일한 뒤 인터프리터에 의해 실시간으로 번역되어 실행된다.
JIT 컴파일러는 반복되어 사용되는 코드나 기계어로 변환 시 많은 리소스가 필요한 부분을 코드가 실행되는 과정(Just-In-Time)에 실시간으로 변환(기계어)하여 캐싱한다.
Java는 이러한 최적화 과정이 존재하기에 인터프리터 언어(Python) 보다 좋은 실행 성능을 낼 수 있다.
6. JVM 구성 요소
- JVM은 크게 클래스 로더 시스템(Class Loader),실행 엔진(Execution Engine), Runtime Data Area 나뉘어져 있다.
(1) 클래스 로더 시스템 : JRE의 일부로, 바이트코드를 실행할 때 class 객체를 메모리에 load하는 요소
자바 소스 프로그램이 컴파일되어 실행되기까지의 순서를 간략하게 확인
개발자가 자바 언어를 사용하여 프로그램 작성 .java
작성 한 프로그램을 컴파일 .class
프로그램 실행에 필요한 .class 파일들을 모두 읽어 연결
프로그램 실행 전 메모리 초기화 작업 진행
바이트 코드로 작성된 프로그램을 인터프리터가 기계어로 번역하여 실행
클래스 로더 시스템은 컴파일된 바이트코드들을 읽어 연결한 뒤 메모리에 저장하는 역할을 수행
내부적으로는 로딩, 링크, 초기화의 단계가 존재
클래스 로더 시스템 초기화 단계에서 전역 변수를 메모리에 할당하기 때문에 필요 이상으로 전역 변수를 남용할 경우 메모리 이슈를 겪을 수 있음
(2) 실행 엔진 : 메모리에 load된 바이트코드를 실행하는 역할
클래스 로더 시스템에 의하여 실행에 필요한 준비 과정이 완료되었다면 이제 인터프리터를 사용하여 바이트 코드를 번역하여 실행할 차례이다.
실행 엔진 내부적으로는 인터프리터, JIT 컴파일러, GC가 있다.
< 인터프리터 >
컴파일된 .class의 바이트코드를 실행하는 역할
< JIT 컴파일러 >
프로그램이 실행될 때 인터프리터가 바이트코드를 읽어 기계어로 번역하지만 프로그램에는 반복적으로 사용하는 코드가 존재한다.
반복적으로 사용되는 코드를 매 번 번역하는 것보다는 최초 1회만 번역하여 특정 저장소(캐시)에 저장 한 뒤 추가 참조가 필요할 때마다 불러온다면 성능 향상을 이끌어 낼 수 있을 것이다.
이 역할을 수행하는 것이 JIT 컴파일러이다.
< GC >
프로그램이 실행되면서 특정 데이터를 저장할 때 주로 메모리를 사용한다.
다양한 로직이 순차적으로 실행되다 보면 한정돼있는 메모리는 여러 데이터로 점령될 것이다.
더 이상 참조되지 않는 데이터를 정리하는 역할을 수행하는 것이 GC이다.
(3) Runtime Data Area : JVM의 메모리 영역
- 클래스 영역> 실행에 필요한 클래스들을 로드하여 저장> 내부에서 메소드 영역과 상수 영역으로 나뉘어 저장
- 가비지 컬렉션 힙 영역> GC에 의해 관리되는 영역> 동적 메모리 할당 영역> 소스상에서 new 연산자로 객체를 만들 때 할당되는 영역
- 런타임 스택 영역> 프로그램 실행 중 발생하는 메소드 호출과 복귀에 대한 정보를 저장
- 네이티브 메소드 스택 영역> 자바에서 하드웨어를 직접 제어하는 기능이 없기 때문에, 필요한 경우 c언어와 같은 다른 언어의 기능을 빌려 사용한다.. 이떄!!! 사용하는 기술이 JNI(Java Native Interface)이다.. 네이티브 메소드들이 바이트코드로 변환되면서 사용되고 기록되는 것
7. JDK와 JRE의 차이
JDK
|
JRE
|
Java Development Kit로 오라클 자바 9부터는 JRE 포함하고 있으며 개발에 필요한 여러 가지 툴을 제공
|
Java Runtime Environment로 바이트 코드로 컴파일된 자바 프로그램을 실행할 때 사용
|
>> 자바 언어로 프로그램을 '개발'하기 위해서는 ?? JDK 설치 필요
>> 자바 언어로 작성된 프로그램을 '실행'하기 위해서는 ?? JRE 설치 필요
Q. javac는 어디에 들어있을까???
> 개발할 때 필요한 것이기 때문에 JDK에 들어있다!!!