1. JVM이란 무엇인가?
Java Virtual Machine의 약어로 자바 가상 머신 이며 자바 바이트 코드를 실행할 수 있는 주체이다.
자바 프로그램은 완벽한 기계언어가 아닌 중간 언어인 바이트 코드로 컴파일 되며 이 바이트 코드를 실행시키기 위해서는 JVM이 필요하다.
Java는 JVM 위에서 작동되기 때문에 운영체제 마다 JVM만 준비되어 있다면 같은 자바 코드를 어떠한 운영체제에서도 실행시킬 수 있으며 이 때문에 자바를 "이식성"이 좋은 언어라고 이야기 한다. 그러므로 JVM의 자바의 운영체제라고도 표현할 수 있다.(JVM은 실제로 GC(Garbage Collection)라는 과정을 통해 메모리를 자동으로 관리해준다.)
JVM은 운영체제에 종속적이며 JDK 또는 JRE를 설치할 시 함께 설치 된다.
JVM의 구성 요소는 자세히 후술하도록 하겠다.
2. Java를 컴파일 하는 방법
자바를 실행하기 위해서는 우선 Java를 실행시키기 위한 환경을 구성해야 하는데 JDK또는 JRE를 설치하면 되며 자바를 개발하기 위해서는 JDK를 설치하면 된다.
JDK의 설치 법 같은 경우에는 굉장히 많은 곳에 정리되어 있으므로 생략한다.
2 - 1. Java가 컴파일 되는 과정
앞선 "1. JVM이란 무엇인가?" 에서 설명한 것과 같이 Java는 중간 언어인 Byte Code로 변환되어 그 Byte Code가 JVM의 클래스 로더에 의해서 JVM 내부로 로드되어 실행되게 된다.
우선 Java의 코드가 작성되어 있는 파일은 .java로 저장되게 된다.
이 Java 파일을 Byte Code로 바꾸기 위해서는 다음 명령어를 사용하면 된다.
javac main.java
이렇게 되면 .java 파일은 .class 파일로 변환되게 되는데 이것이 바로 Byte Code 이다.
이 Byte Code를 실행시키기 위해선 다음과 같이 하면 된다.
java main.class
다음과 같이 하면 파일이 실행된다.
2 - 2. 그래서 컴파일 되는 과정은?
JVM안에는 실행 엔진으로 Interpreter가 내장되어 있는데 이 방식은 코드를 한줄씩 읽어 들이는 방식이다.
인터프리팅 방식으로 코드를 읽어들여 생기는 장점은 코드를 한줄씩 읽어 들여 실행하기 때문에 별도의 빌드 과정을 거치지 않고 빠르게 실행이 가능하다.
하지만, 인터프리팅 방식은 컴파일 방식에 비해서 실행시키는 동안 한줄씩 컴파일 하기 때문에 속도 자체는 느린 단점이 존재한다.
이를 해결하기 위해 JIT(Just In Time) Complier가 존재하며 이 방식은 인터프리팅 방식으로 코드를 한줄씩 기계어로 생산해 내며 해당 기능에 해당하는 기계어 코드를 캐싱을 하여 재사용 하도록 한다.
(JVM 자체에서 최적화 해준다.)
이를 통해 인터프리터 언어의 속도 저하를 어느정도 극복할 수 있게 되었다.
3. Byte Code가 무엇일까?
Java Byte Code의 어원은 코드의 명령어 크기가 1byte여서 자바 바이트코드라 부르며 자바 바이트 코드의 확장자는 .class이다.
CPU는 바이트코드를 이해할 수 없으며 이는 가상머신을 통해서만 이해가 가능하다.
바이트코드의 개념은 자바에만 존재하는 것은 아니며 가상머신에서 실행시키기 위한 중간 언어를 일반적으로 바이트코드라고 명명한다.(C#에서도 같은 용어를 사용한다.)
이를 JVM이 해석하여 CPU가 해석 가능한 "기계어" 즉 "바이너리 코드"로 변환한다.
4. JIT 컴파일러는 무엇이며 어떻게 동작될까?
Java에는 인터프리터 엔진이 존재하며 자바는 기본적으로 각 코드 라인별로 실행을 시키는 인터프리팅 방식으로 작동하게 된다. 하지만 앞서 설명한 것 처럼 이는 성능에 악영향을 끼치고 이것을 최적화 하기 위해 나온 방식이 JIT 방식이다.
매번 호출시 마다 컴파일을 하여 기계어를 생성한다면 그 비용이 크기 때문에 이를 기준에 따라서 캐싱해 놓고 즉시 기계어를 호출 할 수 있도록 지원한다.
JIT을 이용하면 메소드가 처음으로 호출될 때 컴파일 되지 않으며 JVM은 각 메소드에 대해 사전에 정의된 "컴파일 임계값"에서 시작되고 해당 메소드가 호출될 때마다 호출 개수를 감소시킨다.
호출 개수가 0에 도달하는 순간 해당 메소드에 대해 JIT 컴파일이 동작된다.
따라서, 이를 통하여 자주 사용되는 메서드는 컴파일 하고 자주 사용되지 않는 메서드는 컴파일 하지 않는 방식으로 성능을 최적화 시킨다.
JIT은 다양한 수준으로 메서드를 컴파일 할 수 있으며 cold, warm, hot, veryHot 또는 scorhing으로 나뉜다.
최적화의 레벨이 높을수록 성능은 좋아질 수 있으나 CPU 및 메모리 측면에서 컴파일 비용은 더 높아진다.
Jit을 사용하지 않도록 설정도 가능하지만 일반적으로는 권장되지 않는다.
최적화에 대한 더 자세한 내용은 4)번을 참조.
5. JVM의 구성요소
JVM은 위 그림과 같은 구조를 가지고 있으며 각 위치에 대한 설명을 하도록 하겠다.
5 - 1. Class Loader
앞서서 설명한 byte code로 변환된 .class 파일을 로드하여 class 객체를 생성한다.
클래스 로더는 Complie Time이 아닌 Runtime에 로드 된다.
로딩, 링크 ,초기화 세 가지 과정을 거친다.
5 - 2. Execution Engine
execution은 실행한다는 뜻으로 말그대로 바이트 코드를 읽어서 실행하는 역할을 한다.
위 4. 에서 설명한 Interpreter와 JIT 컴파일러로 분류된다.
상세한 컴파일 과정은 앞부분에서 설명했기 때문에 생략한다.
5 - 3. Garbage Collector 영역
Garbage Collection은 JVM에서 메모리를 관리해주는 역할을 한다.
Heap영역에 있는 사용되지 않는 객체를 정리해준다.
상세한 GC과정에 대해서 굉장히 잘 정리된 글이 있어서 첨부한다.
https://d2.naver.com/helloworld/1329
(기회가 된다면 한번 따로 정리해보겠지만 위 글보다 잘 정리할 자신은 없다..)
5 - 4. Runtime Area
JVM의 메모리 영역으로 클래스들이 로드된 후 데이터들을 적재하는 공간이다.
(1) Method area
모든 스레드가 공유하는 영역이며 class, 인터페이스, 메서드, 필드, static 의 정보들이 저장되어있다.
(2) Heap
우리가 일반적으로 스레드와 프로세스의 차이를 설명할때 나오는 그 힙영역이다.
모든 스레드가 공유하는 영역이며 런타임에 생성되는 Object들이 할당된다.
Garbage Collector가 주기적으로 확인하여 참조되지 않는 메모리들을 관리해준다.
(3) Stack Area
메서드 호출마다 Stack Frame이 쌓이는 영역이며 해당 부분에는 지역변수(원시타입), 반환 주소값, 매개 변수 등이 저장된다. 스택 영역의 경우는 스래드별로 별도로 가지게 되며 해당 메서드가 종료되면 삭제된다.
(4) PC Register
쓰레드가 시작 되는 시점에 생성되며 쓰레드마다 하나씩 존재한다.
쓰레드가 어떤 부분을 어떤 명령어로 실행 해야하는지를 기록하고 있으며 현재 수행중인 JVM 명령의 주소를 가지고 있는다.
(5) Native Method Stack
자바 외의 언어로 작성된 코드들을 위한 영역
6. JDK와 JRE의 차이점
JRE = JVM + 표준 클래스 라이브러리
JDK = JRE + 개발에 필요한 도구
실행 자체는 JRE만 있어도 가능하지만 개발을 위해서는 디버깅 툴, 분석에 용이한 도구들을 포함하고 있는 JDK를 설치하는 것이 좋다.
본 글은 백기선님의 자바스터디 커리큘럼을 따라 정리한 내용입니다.
https://github.com/whiteship/live-study/issues/1
참조
1) http://www.tcpschool.com/java/java_intro_programming
2) https://shrtorznzl.tistory.com/82
3) https://ko.wikipedia.org/wiki/%EC%9E%90%EB%B0%94_%EA%B0%80%EC%83%81_%EB%A8%B8%EC%8B%A0
4) https://www.ibm.com/docs/ko/sdk-java-technology/8?topic=reference-jit-compiler
5) 이것이 자바다(책)
'JAVA' 카테고리의 다른 글
5주차. 클래스 (0) | 2022.09.15 |
---|---|
3주차. 연산자 (0) | 2022.09.02 |
2주차. 자바 데이터 타입, 변수 그리고 배열 (0) | 2022.09.02 |