- JVM이란 무엇인가
- 컴파일 하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는가
- JVM 구성요소
- JDK와 JRE의 차이
- JVM이란 무엇인가
JVM은 Java Virtual Machine '자바 가상 머신'을 뜻하는 말로 바이트코드를 실행하는 주체입니다.
자바가 처음 세상에 나왔을 때 WORA (Write Once Run Anywhere) 를 내세워 홍보하였습니다.
한번 작성해서 어디서든 실행할 수 있다는 말로, 자바 코드로 작성한 프로그램은 실행할 환경 (예를 들어 운영체제)에 독립적으로 실행할 수 있음을 뜻합니다.
JVM과 같은 중간언어를 해석해주는 추상화된 장치가 없는 언어들은, 운영체제가 바뀔 때마다 그에 맞는 실행 가능한 프로그램을 만들어야 합니다.
이런 불편함을 해소하기 위해 바이트 코드를 기계어로 번역해주는 과정을 한 번 더 하며 성능을 포기하고 편리함을 선택하였습니다.
그래서 처음 자바를 배울 때 다른 언어에 비해 실행 속도가 느린다는 말을 들었을 겁니다.
왜냐하면 직접 실행 가능한 코드가 아닌 바이트코드를 만들고, 이 바이트 코드를 JVM이 인터프리터 방식으로 기계어로 번역하며 실행하기 때문입니다.
- 컴파일 하는 방법
컴파일을 한다는 것은 .java 파일을 class 파일(바이트 코드)로 만든다는 것을 의미합니다.
JDK(Java Development Kit) 자바 개발 도구를 설치하면 bin 폴더 안에 javac 라는 java compiler가 포함되어 있습니다.
이 명령을 사용해서 .class 파일을 만듭니다.
명령프롬프트를 사용해서 컴파일 하기 위해서는 현재 위치를 소스파일이 있는 곳으로 이동해야 합니다.
저는 C:\java\Main.java 파일을 만들었습니다.
그리고 javac Main.java 명령어를 입력하면, 작성한 코드에 문제가 없을 경우 .class 파일의 바이트코드가 생성됩니다.
여기서 한 번 생각해볼 수 있는건 어떻게 .javac 명령어를 사용할 수 있었을까요?
환경변수라는 것에 대해 알 필요가 있습니다.
환경변수는 운영체제가 실행할 수 있는 실행파일들이 위치한 디렉토리를 지정해두어 이를 운영체제가 참조해서 사용할 수 있도록 한 것입니다.
두 번째 방법은 default 패키지를 사용하지 않았을 때 방법입니다.
- 실행하는 방법
실행할때는 java 명령어를 사용합니다.
- 바이트코드란 무엇인가
프로그램을 실행하는 것은 결국 컴퓨터입니다. 다시 말해 프로그램은 컴퓨터가 이해할 수 있는 형태로 작성되어 있어야 합니다. 자바 문법으로 작성한 .java 파일은 사람이 이해할 수 있는 언어로 작성했기 때문에 컴퓨터는 이해할 수 없습니다. 그렇기 때문에 번역을 통해 컴퓨터가 이해할 수 있는 형태로 만들어 줘야 합니다.
컴퓨터가 이해할 수 있는 형태로 번역하는 것은 JVM이 담당해야 합니다.
그럼 우리는 JVM이 이해할 수 있는 형태로 번역을 해서 줘야 합니다.
이때 JVM이 이해할 수 있는 형태가 바이트 코드입니다.
자바에서 javac 명령을 통해 컴파일을 하면 .class 확장자를 갖는 바이트코드가 만들어지고, JVM이 바이트코드를 실행합니다.
중간언어라고도 합니다.
- JIT 컴파일러란 무엇이며 어떻게 동작하는가
JIT 컴파일러는 Just In Time 컴파일러로 바이트코드를 기계어로 번역하여 실행하는 것을 뜻합니다.
인터프리터 방식은 바이트 코드를 한 줄씩 읽으면서(번역하면서) 코드를 실행합니다. 그렇기 때문에 동일한 메소드를 실행하는 경우 중복해서 번역하여 비효율적입니다.
이를 방지해서 보다 좋은 성능을 낼 수 있게 하기 위해 JIT 컴파일러는 변역한 내용을 캐싱해 두었다가 동일한 메소드를 실행할 경우 다시 번역하지 않고 캐싱된 내용을 실행하는 것으로 알고 있습니다.
JIT 컴파일는 Just In Time 컴파일로 다른 말로 동적 번역이라고 합니다.
이것은 프로그램을 실제로 실행하는 시점에 기계어로 번역하는 컴파일 기법입니다.
전통적으로 컴퓨터 프로그램을 만드는 방법은 두가지가 있는데
1. 인터프리트 방식과
2. 정적 컴파일 방식으로 나눌 수 있습니다.
인터프리트 방식은 실행 중 프로그래밍 언어로 읽으며 해당 기능에 대응하는 기계어 코드를 실행합니다.
정적 컴파일은 실행하기 전에 프로그램 코드를 기계어로 번역합니다.
JIT 컴파일러는 두 가지 방식을 혼합한 방식으로 생각할 수 있습니다.
실행 시점에 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱합니다.
그리고 같은 함수가 여러 번 볼릴 때 매번 기계어 코드를 생성하는 것을 방지합니다.
최근 JVM, .NET, V8(node.js) 에서 JIT 컴파일러를 지원합니다.
- JVM 구성요소
JVM은 크게 4가지 구성 요소를 가집니다.
1. Class Loader
2. GC (Garbage Collector)
3. Execution Engine
4. Runtime Data Area
1. Class Loader
- JRE의 일부로, 바이트코드를 실행할 때 class 객체를 메모리에 생성하는 요소이다.
클래스의 인스턴스를 생성하면 Class Loader를 통해 메모리에 로드한다.
2. GC(Garbage Collector)
- 자바는 메모리 관리를 사용자가 아닌 JVM이 알아서 해줍니다.
GC는 더 이상 참조되지 않는 메모리를 정리해줍니다.
GC가 언제 호출되는지는 알 수 없으며, 심지어 사용자가 호출하더라도 메모리 정리할 필요가 없다고 판단하면
실행하지 않습니다.
3. Execution Engine
- 메모리에 로드 된 바이트 코드를 실행하는 역할을 합니다.
Class Loader를 통해 Runtime Data Area에 배치된 바이트코드는 Execution Engine에 의해 실행 됩니다.
이넡프리터 방식이나 JIT 방식으로 실행합니다.
4. Runtime Data Area
- JVM의 메모리 영역입니다.
크게 4가지 영역으로 구분할 수 있습니다.
a. 클래스 영역
- 실행에 필요한 클래스들을 로드하여 저장합니다. 내부에서 메소드 영역과 상수 영역으로 또 나뉘어 저장됩니다.
b. 가비지 컬렉션 힙 영역
- GC에 의해 관리되는 영역입니다. 동적 메모리 할당 영역이라고도 하며, 소스 상에서 new 연산자로 객체를
만들 때 할당되는 영역입니다.
c. 런타임 스택 영역
- 프로그램 실행 중 발생하는 메소드 호출과 복귀에 대한 정보를 저장합니다.
d. 네이티브 메소드 스택 영역
- 자바에는 하드웨어를 직접 제어하는 기능이 없기 때문에 필요한 경우 c언어와 같은 다른 언어의 기능을 빌려
사용합니다. 이때 사용하는 기술이 JNI(Java Native Interface) 기술로 네이티브 메소드들이 마이트 코드로
되면서 사용되고 기록하는 영역입니다.
- JDK와 JRE의 차이
JDK - Java Development Kit (자바 개발 도구)
JRE - Java Runtime Environment (자바 실행 환경)
즉, 자바 언어로 프로그램을 개발하기 위해서는 JDK를 설치해야 하고 자바 언어로 작성된 프로그램을 실행하기 위해서는 JRE를 설치해야 합니다. JDK를 설치하면 JRE가 포함되어 설치됩니다.
[참조]
blog.naver.com/hsm622/222138523668
'JAVA' 카테고리의 다른 글
연산자 (0) | 2021.06.20 |
---|---|
자바 데이터 타입, 변수 그리고 (0) | 2021.04.25 |
람다식 (0) | 2021.04.15 |
제네릭(Generic) (0) | 2021.02.27 |
I/O (Input/Output) (0) | 2021.02.20 |