목표
JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.
학습할 것
- JVM이란 무엇인가
- 컴파일 하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는지
- JVM 구성 요소
- JDK와 JRE의 차이
- javac 옵션
JVM이란 무엇인가
- JVM - Java Virtual Machine
- JAVA Byte Code를 운영체제에 맞게 해석해주는 역할 즉, 자바를 실행해주는 머신
- 자바 어플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행한다.
- 자바와 OS사이에서 중개자 역할을 하며 자바로 작성된 모든 어플리케이션은 모두 JVM에서만 실행된다. ( 자바가 OS에 독립적인 이유 )
- 하지만 JVM은 OS에 종속적이기 때문에 해당 OS에서 실행가능한 JVM이 필요하다.
- 다른 어플리케이션 코드는 OS만 거치고 하드웨어로 전달된다.( OS에 종속적이다. )
- JAVA 어플리케이션은 JVM을 한번 더 거치고, 하드웨어에 맞게 완전히 컴파일 된 상태가 아니고 실행 시에 interpret되기 때문에 속도가 느리다는 단점을 가지고 있다.
- 요즘엔 바이트코드 ( 컴파일된 자바코드 )를 하드웨어의 기계어로 바꿔주는 JIT컴파일러와 향상된 최적화 기술이 적용되어서 속도의 격차가 많이 줄었다.
- 내부의 GC(Garbage Collector)가 있어 사용되지 않는 메모리를 정리해 메모리 관리를 해준다.
컴파일 하는 방법
소스코드.java
작성javac.exe
즉, 자바 컴파일러를 통해 자바 소스코드를 바이트 코드로 컴파일한다. ( .class파일 생성 )
실행하는 방법
java.exe
즉, 자바 인터프리터를 통해 바이트 코드를 실행한다.- .class파일 실행
- 내부적인 진행순서
- 프로그램의 실행에 필요한 클래스(.class파일)을 로드
- 클래스파일 검사 ( 파일형식, 악성코드 체크 )
- 지정된 클래스에서 main(String[] args) 호출
- 하나의 자바 어플리케이션에는 main메서드를 포함한 클래스가 반드시 하나는 존재해야 한다!
- 내부적인 진행순서
바이트코드란 무엇인가
- 자바 컴파일러에 의해 JVM이 이해할 수 있는 언어로 변환된 .class 파일
- 자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1byte라서 바이트코드라고 불림
JIT 컴파일러란 무엇이며 어떻게 동작하는지
출처) https://beststar-1.tistory.com/3
- 앞서 말한 것처럼 자바는 바이트코드로 한번 컴파일하는 과정과 바이트코드를 인터프리터 하는 방식 2가지로 진행된다. 고로, 속도가 느리다.
- 이런 속도측면에서 해결하기 위해 나온 것이 JIT컴파일러이다.
- JIT 컴파일러란?
- Just In Time 컴파일러
- 런타임시에 JVM에서만 돌아가는 자바 바이트 코드를 해당 플랫폼에 맞는 기계어 ( native code ) 로 컴파일해주는 특수한 컴파일러
- 어떻게 동작하나?
- 번역된 코드를 캐싱해둔 다음 똑같은 코드가 있다면 번역하지 읺고 캐싱해둔 값을 사용하여 매번 기계어 코드가 생성되는 것을 방지해 인터프리팅 시간을 단축시킨다.
- JVM이 호출되는 메서드 각각에 대한 호출마다 호출 횟수를 누적해서 그 횟수가 특정 수치를 초과 할 때 컴파일하는 것
- 횟수때문에 딱 한번만 실행될 경우 인터프리터 방식으로 실행
- 인터프리터와 동시에 돌고 있다 ( 쓰레드 개념 )
JVM 구성 요소
출처) https://www.inflearn.com/course/the-java-code-manipulation/dashboard
- JVM은 크게 4가지 구성요소로 이루어져 있다.
- 클래스 로더 시스템
- 바이트코드를 읽어서 JVM의 실행 엔진이 사용할 수 있도록 Runtime Data Area ( 메모리 ) 에 적절히 배치하는 역할
- 3가지 로딩 → 링크 → 초기화 순으로 진행된다.
- 로딩
- .class파일을 읽어서 바이너리 코드로 만들고 이를 메모리의 메소드 영역에 저장하는 과정
- 저장하는 데이터는 다음과 같다.
- Fully-Quailified Class Name(FQCN)
- 클래스 로더, 클래스 패키지 경로, 패키지 이름, 클래스 이름을 모두 포함한 값
- 예) java.lang.Character$Subset
- Class, Interface, Enum을 구분하여 저장
- 메소드와 변수
- Fully-Quailified Class Name(FQCN)
- 로딩이 끝나면 해당 클래스 타입의 객체를 생성하여 메모리의 힙 영역에 저장한다.
- BootStrap → Extension → Application Loader 순으로, 앞의 Loader가 로딩할 수 없으면 그 다음 Loader가 읽어내는 식
- 개발자가 애플리케이션 구동을 위해 직접 작성한 대부분의 클래스는 애플리케이션 클래스로더에 의해 로딩된다.
- 링크
- 코드 내부의 래퍼런스를 연결하는 과정
- Verify
- .class 파일 형식이 유효한지 검사
- Perpare
- static변수와 기본 값에 필요한 메모리 준비
- Resolve ( Optional )
- 심볼릭 메모리 래퍼런스를 실제 메모리 래퍼런스로 교체
- Optional인 이유는, 이 때 교체될 수 있고, 이후 사용이 일어날 때에 동적으로 교체될 수도 있기 때문이다.
- 초기화
- static변수를 초기화하고 값을 할당하는 과정
- 로딩
- 메모리( Runtime Data Areas )
- 프로그램을 수행하기 위해 운영체제로부터 할당받는 메모리 영역
- 힙 영역
- 인스턴스화 된 모든 클래스 인스턴스와 배열,객체를 저장하며 모든 JVM 쓰레드에 공유되는 공유 자원
- 여기서 인스턴스 변수 저장
- GC에 있어서만 회수 가능
- 메소드 영역
- 클래스 수준의 정보 ( 클래스 이름, 부모 클래스 이름, 메소드, 변수 등 ) 저장
- 여기서 클래스 변수 저장 ( static 변수, 일반 변수 등 )
- 힙과 마찬가지 JVM 쓰레드에 공유되는 공유 자원
- 스택 영역
- 인스턴스 및 지역 변수의 참조 주소들을 저장
- 쓰레드마다 런타임 스택을 만들고, 스택 프레임( 메소드 call ) 을 쌓는다.
- 메소드 실행이 완료되거나 예외가 던져지면 스택에서 빠진다.
- PC
- 쓰레드마다 가지고 있는 Program Counter
- 현재 실행할 부분을 가르키고 있다.
- 네이티브 메소드 스택
- 네이티브 메소드 호출할 때 사용하는 별도의 스택
- 네이티브 메소드는 java가 아닌 c와 같은 언어로 구현된 메소드
- 실행 엔진
- 인터프리터
- 바이트코드를 한줄 한줄 읽어서 네이티브 코드로 변환
- JIT 컴파일러
- GC ( Garbage Collector )
- 더 이상 참조되지 않는 객체를 모아서 메모리 정리
- 인터프리터
4-1. 네이티브 메소스 인터페이스 ( JNI )
- 자바 애플리케이션에서 C, C++, 어셈블리로 작성된 네이티브 키워드를 사용한 함수를 사용할 수 있는 방법 제공
4-2. 네이티브 메소드 라이브러리
- C, C++로 작성된 라이브러리
JDK와 JRE의 차이
출처) https://www.inflearn.com/course/the-java-code-manipulation/dashboard
- JDK ( Java Development Kit )
- 자바 개발 도구
- JRE + 개발에 필요한 툴 ( javac.exe 등 )
- JRE ( Java Runtime Environment )
- 자바 실행 환경
- 자바로 작성된 응용프로그램이 실행되기 위한 최소환경
- JVM + 클래스 라이브러리 ( Java API )
javac 옵션
- 11버전에서 컴파일한 바이트코드는 8버전에서 실행 불가능
- 8버전에서 컴파일한 바이트코드는 11버전에서 실행 가능
- 이를 방지하기 위해 컴파일러시 옵션을 줘서 낮은 버전에서도 실행 가능하게 할 수 있다.
- javac
- source: The version that your source code requires to compile.
- target: The oldest JRE version you want to support.
- javac(11버전) -source 1.8 -target 1.8 hello.java
- 이런식으로 컴파일시 8버전으로도 실행가능
추가 학습
- 컴파일러 , 인터프리터
- 컴파일러 : 소스코드를 한꺼번에 컴퓨터가 읽을 수 있는 기계어로 변환
- 인터프리터 : 소스코드를 빌드시에 아무것도 하지 않고 런타임시에 한줄 한줄 읽어가며 변환
- javap.exe
- 역어셈블러
- class파일을 java파일로 만들어준다.
Reference
- 남궁성. Java의 정석 3판. 도우출판, 2016.
- https://www.youtube.com/watch?v=UzaGOXKVhwU
- https://honbabzone.com/java/java-jvm/
'Back-End > 백기선님의 자바 스터디' 카테고리의 다른 글
5주차 - 클래스 (0) | 2022.03.20 |
---|---|
4주차 - 제어문 (0) | 2022.03.16 |
3주차 - 연산자 (0) | 2022.03.10 |
2주차 - 자바 데이터 타입, 변수 그리고 배열 (0) | 2022.03.10 |
백기선 자바 라이브 스터디 (0) | 2022.03.10 |
댓글