-
1주차 과제: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.객체지향 2021. 1. 17. 20:09
목표
자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기.
학습할 것
- JVM이란 무엇인가
- 컴파일 하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는지
- JVM 구성 요소
- JDK와 JRE의 차이
1. JVM이란 무엇인가
- Java Virtual Machine '자바 가상 머신'을 뜻하는 말로 바이트코드를 실행하는 주체
- 한번 작성해서 어디서든 실행할 수 있다는 말로, 자바 코드로 작성한 프로그램은 실행할 환경에 독립적으로 실행
- 정해진 약속(Java byte code)만 지켜지면 JVM은 자신의 환경(OS)에 맞게 Java byte code를 실행
JVM과 같은 중간언어를 해석해주는 추상화(여러 가지 사물이나 개념에서 공통되는 특성이나 속성 따위를 추출하여 파악하는 작용)된 장치가 없는 언어들은, 운영체제가 바뀔 때마다 그에 맞는 실행 가능한 프로그램을 만들어야 했다.
이런 불편함을 해소하기 위해 바이트 코드를 기계어로 번역해주는 과정을 한 번 더 거치며 성능을 포기하고 편리함을 선택했다.
직접 실행 가능한 코드가 아닌 바이트 코드를 만들고, 이 바이트 코드를 JVM이 인터프리터 방식으로 기계어로 번역하여 실행하는 방식이다.
2. 컴파일 하는 방법
컴파일을 한다는 것은 .java 파일을 .class 파일(바이트코드)을 만든다는 것을 의미한다.
JDK(Java Development Kit) 자바 개발도구를 설치하면 bin 폴더 안에 javac라는 java compiler가 포함되어 있다.
이를 사용해서 .class 파일을 생성한다.
코드를 작성한 디렉토리로 이동하여 javac study.class라고 명령을를 입력 하면 .class 파일의 바이트 코드가 생성된다.
Java를 설치할때 환경 변수를 설정했는데 이 환경 변수를 통해서 운영체제가 실행할 수 있는 실행 파일들이 위치한 경로를 지정하여
이를 운영체제가 참조해서 javac 명령어를 사용할 수 있도록 한 것이다.
3. 실행하는 방법
실행할때는 java 명령어를 사용하여 실행한다.
4. 바이트코드란 무엇인가?
프로그램을 실행하는 것은 컴퓨터이다.
다시 말해 프로그램은 컴퓨터가 이해할 수 있는 형태로 작성되어 있어야 한다.
자바 문법으로 작성한 .java 파일은 사람이 이해할 수 있는 언어로 작성했기 때문에 컴퓨터는 이해할 수 없다.
그렇기 때문에 번역을 통해 컴퓨터가 이해할 수 있는 형태로 만들어 줘야한다.
컴퓨터가 이해할 수 있는 형태로 번역하는 것은 JVM이 담당한다.
그럼 우리는 JVM이 이해할 수 있는 형태로 번역을 해서 전해줘야한다.
이때 이 JVM이 이해할 수 있는 형태가 바이트코드이다.
자바에서 javac 명령을 통해 컴파일을 하면 .class 확장자를 갖는 바이트코드가 만들어지고, JVM이 바이트코드를 실행한다.
5. JIT 컴파일러란 무엇이며 어떻게 동작하는지?
JIT 컴파일러는 Just In Time 컴파일러로 바이트코드를 기계어로 번역하여 실행하는 것을 뜻한다.
인터프리터 방식은 바이트코드를 한 줄씩 읽으면서 코드를 실행하기 때문에 동일한 메소드를 실행하는 경우 중복해서 번역하는 비효율이 있다.
이를 방지해서 보다 좋은 성능을 낼 수 있게 하기 위해 JIT 컴파일러는 번역한 내용을 캐싱해 두었다가 동일한 메소드를 실행할 경우 다시 번역하지 않고 캐싱된 내용을 실행한다.
JIT 컴파일은 동적 번역이라고 하는데 이는 프로그램을 실제로 실행하는 시점에서 기계어로 번역하는 컴파일 기법이다.
전통적으로 컴퓨터 프로그램을 만드는 방법은 두가지가 존재
1. 인터프리터 방식(프로그래밍 언어를 읽으며 해당 기능에 대응하는 기계어 코드를 실행)
2. 정적 컴파일 방식(실행하기 전에 프로그램 코드를 기계어로 번역)
JIT 컴파일러는 두 가지 방식을 혼합한 방식으로 실행 시점에 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱한다.
그리고 같은 함수가 여러 번 호출 될때 캐싱된 코드를 재사용하여 여러번 코드를 생성하는 것을 방지한다.
JVM과 .NET V8(node.js)에서 JIT 컴파일러를 지원한다.
6. JVM 구성 요소
JVM은 크게 네가지 구성 요소를 가진다.
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의 메모리 영역이다.
- 크게 네가지 영역으로 구분할 수 있다.
1. 클래스 영역: 실행에 필요한 클래스들을 로드하여 저장, 내부에서 메소드 영역과 상수 영역으로 또 나뉘어 저장
2. 가비지 컬렉션 힙 영역: GC에 의해 관리되는 영역으로 소스상에서 new 연산자로 객체를 만들 때 할당되는 영역
3. 런타임 스택 영역: 프로그램 실행 중 발생하는 메소드 호출과 복귀에 대한 정보를 저장한다.
4. 네이티브 메소드 스택 영역: 자바는 하드웨어를 직접 제어하는 기능이 없기 때문에, 필요할 경우 다른 언어의 기능을 빌려 사용한다.
이때 사용하는 기술이 JNI 기술로 네이티브 메소드들이 바이트 코드로 변호나 되면서 사용되고 기록하는 영역이다.
7. JVM 동작 방식
1. Class Loadder을 통해 Class파일을 JVM으로 로딩
2. 로딩된 Class 파일을 Execution Engine으로 해석
3. 해석된 프로그램을 JVM Memory에 배치 실행
8. JVM 구조
.java : Java코드
javac : Java코드를 Java byte code로 변환
.class : Java byte code
Class Loader : class 파일을 로딩 Runtime Data Area에 적재
JVM Memory : 시스템(OS)에게 할당받은 메모리
Execution Engine : Java byte code 해석기
Native method, Libraries : Java로 작성된 코드는 JVM을 통해 실행하기때문에 시스템에 접근하기가 힘들다 그래서 외부 Native언어
C, C++을 통해 작성하고 JNI(Native method interface)로 연계해 실행
9. JDK와 JRE의 차이
JDK: Java Development Kit => 자바 개발 도구
- JRE의 상위 집합이며 Java 프로그래머 용 도구
JRE: Java Runtime Environment => 자바 실행 환경
- Java 프로그램을 실행하는데 필요한 소프트웨어 패키지
- Java 클래스 라이브러리와 JVM이 포함되어있다.
- 즉 실행환경을 제공해준다.
즉, 자바 언어로 프로그램을 개발하기 위해서는 JDK를 설치해야 하고
자바 언어로 작성된 프로그램을 실행하기 위해서는 JRE를 설치해야 한다.
JDK를 설치하면 JRE가 포함되어 같이 설치된다.
10. JDK 구성
'객체지향' 카테고리의 다른 글
2주차 과제: 자바 데이터 타입, 변수 그리고 배열 (0) 2021.01.19 고급 객체지향 프로그래밍(3) (0) 2020.01.20 고급 객체지향 프로그래밍(2) (2) 2020.01.17 고급 객체지향 프로그래밍(1) (1) 2020.01.17