목차
1주차 - JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가
JVM이란 무엇인가 & JVM 구성 요소
자바 실행 단계
JVM(Java Virtual Machine)
- 자바를 실행하기 위한 가상머신: 자바로 작성된 애플리케이션은 모두 JVM에서만 실행됨(자바 애플리케이션 실행 시 필수)
- 운영체제 위에서 동작하는 프로세스로 자바 코드를 컴파일 해서 얻은 바이트 코드를 해당 운영체제가 이해할 수 있는 기계어로 바꿔실행 시켜주는 역할
- GC(Garbage Collection)을 이용하여 자동으로 메모리 관리
- Garbage Collection
- 메모리 힙(Heap)
- 프로그램이 실행되면 아래 그림과 같이 4개의 메모리 영역을 가지게 된다.
- 이중 Heap 영역은 사용자가 동적할당을 할 경우 메모리에 저장된다.
- C언어에서는 malloc, java에서는 new 키워드로 Heap 영역에 메모리를 할당할 수 있다.
- Heap 메모리의 해제는 C에서는 free 함수로 해제하며, java에서는 JVM에서 가비지 컬렉터가 지우는 시점에 해제
- 메모리 힙(Heap)
- 자동으로 Heap 영역의 쓰지 않는 메모리를 회수
- Garbage Collection
- 일반 애플리케이션 코드: OS만 거치고 하드웨어로 전달 - Java 애플리케이션 코드: JVM을 거치고 OS를 거친 후 하드웨어로 전달, 하드웨어에 맞게 완전히 컴파일된 상태 X 실행 시에 해석되기 때문에 속도가 느림(요즘에는 바이트코드를 하드웨어의 기계어로 바로 번역해주는 JIT 컴파일러 등이 있어서 이 문제는 많이 해결됨) |
- 자바가 운영체제 종류에 영향을 받지 않고 실행 가능하도록 함 → Java 애플리케이션은 JVM하고만 상호작용을 하기 때문에 OS와 하드웨어에 독립적이라 OS의 영향을 받지 않음
JVM 구성 요소
1. 클래스 로더 시스템(Class Loader) → 실행에 필요한 준비 과정
- 자바 바이트 코드 파일인 .class 파일을 읽어 연결한 뒤 메모리에 저장하는 역할을 수행
- 내부적으로는 로딩, 링크, 초기화의 단계가 존재
- 클래스 로더 시스템 초기화 단계에서 전역 변수를 메모리에 할당하기 때문에 필요 이상으로 전역 변수를 남용할 경우 메모리 이슈를 겪을 수 있음
- 엄밀히 말하자면 JDK가 아닌 JRE의 구성요소
2. 실행 엔진(Execution Engine) → 인터프리터를 사용하여 바이트 코드를 번역하여 실행
- 클래스 로더를 통해 JVM으로 로딩된 자바 바이트 코드를 명령어 단위로 읽어서 실행
- 내부적으로는 인터프리터, JIT 컴파일러 존재
- 인터프리터(Interpreter)
- 자바 바이트 코드를 한 줄씩 번역하고 실행하는 방식
- 컴파일된 .class의 바이트 코드를 실행하는 역할
- JIT(Just In Time) 컴파일러
- Interpreter 방식의 단점을 보완하기 위해 도입된 컴파일러
- 이미 한번 읽어서 Native Code로 변환한 소스코드는 캐싱을 통해 저장해둬서 다시 번역하지 않기 때문에 실행 속도를 높일 수 있음
- 자세한 내용은 후술
- 인터프리터(Interpreter)
3. 메모리(Runtime Data Area)
- JVM의 메모리 영역
- 자바 애플리케이션을 실행할 때 데이터를 적재하는 영역
- 메모리(Runtime Data Area) 구성
- Method Area (Class Area)
- 모든 쓰레드가 공유하는 영역으로 JVM이 시작될 때 생성
- 클래스와 인터페이스의 상수, 메서드와 필드 정보, static, final 변수, 타입 정보 등을 보관
- Heap Area
- 동적으로 생성된 오브젝트와 배열이 저장되는 영역으로, Garbage Collection에 의해 관리됨
- Stack Area
- 메서드가 호출 되면 메서드 안에서 사용하는 값들과 매개 변수, 지역 변수, 리턴 값 등을 저장한 뒤, 메서드가 종료될 때 함께 삭제되는 데이터들이 임시적으로 저장되는 영역
- 메서드가 호출되는 순서대로 쌓임
- PC Register
- 현재 어떤 명령어가 실행되어야 하는지에 대해 저장하는 레지스터
- 현재 수행 중인 JVM 명령의 주소를 갖고 있음
- Native Method Stack
- 자바 이외의 언어로 작성된 Native Code를 위한 영역
- Method Area (Class Area)
4. 가비지 컬렉터(Garbage Collector)
- Heap 영역의 메모리를 자동으로 관리
- 프로그램이 실행되면서 특정 데이터를 저장할 때 주로 메모리를 사용 → 다양한 로직이 순차적으로 실행되다 보면 한정돼있는 메모리는 여러 데이터로 점령될 것
- 더 이상 참조되지 않는 데이터를 정리하는 역할을 수행
컴파일 하는 방법 & 실행하는 방법
컴파일
- 고급언어로 작성된 소스코드를 컴퓨터가 이해할 수 있도록 기계어(native code)로 변환하는 과정
- 자바 컴파일러는 자바 개발 키트(JDK)에 포함되어 있기 때문에 작성된 코드를 컴파일해 바이트코드를 생성하기 위해선 우선 JDK가 필요
- javac.exe는 JDK, java.exe는 JRE에 포함되어 있기에 JDK과 JRE를 설치해야 하지만 과거와 다르게 요즘은 JDK에 JRE가 포함된 형태로 배포되고 있기에 JDK만 설치해도 무관
- .java 파일을 .class 파일로 변환하는 과정
- 컴파일을 위해선 컴파일 작업을 수행할 java compiler가 필요 → java comiler는 jdk를 설치하면 bin 폴더안에 javac라는 이름으로 설치됨
- javac.exe: 자바 소스코드를 컴파일 할때 사용하는 프로그램
- java.exe: 컴파일된 바이트코드를 실행할 때 사용
컴파일 방법
- class 파일 만들기
- $ javac 파일명.java
- javac.exe 사용하여 .java 파일 컴파일
- 컴파일이 정상적으로 완료되면 해당 경로에 소스파일명 .class 생성
- 파일 실행
- $ java 파일명
- java.exe 파일을 사용하여 바이트코드로 컴파일된 .class 실행
- 실행시에는 소스 파일명의 확장자는 붙이지 않음
바이트코드(.class)란 무엇인가
- JVM이 사용자가 작성한 .java 소스 파일을 운영체제에 실행가능한 명령어 집합 파일로 컴파일하는 과정 중에 필요한 코드
- 1차적으로 .java 소스 코드파일을 사용자가 작성하면, JVM이 이를 바이트코드로 컴파일하여 .class 파일로 만든다.
- 2차적으로 운영체제에 작용하는 기계어(native code)로 한번 더 컴파일되어 컴퓨터에 JAVA 프로그램이 실행되는 것
자바 바이트 코드
- JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미
- 자바 컴파일러에 의해 변환되는 코드의 명령어의 크기가 1byte라서 자바 바이트 코드라고 불림
- 자바 바이트 코드는 자바 가상 머신만 설치되어 있다면 어느 운영체제에서도 실행 가능
JIT 컴파일러란 무엇이며 어떻게 동작하는지
JIT 컴파일러(Just-In-Time compilation)
- Interpreter 방식의 단점을 보완하기 위해 도입
- 프로그램을 실제 실행하는 시점에 기계어(native code)로 번역하는 컴파일 기법
- 이미 한번 읽어서 Native Code로 변환한 소스코드는 캐싱을 통해 저장해둬서 다시 번역하지 않기 때문에 실행 속도를 높일 수 있음
JDK와 JRE의 차이
JDK(Java Runtime Environment)
- 자바 개발 도구로 JRE를 포함
- 자바의 모든 기능을 포함한 SDK(개발을 위한 패키지)
- 소프트웨어 개발 키트 (Software development kit, SDK): 일반적으로 소프트웨어 기술자가 사용하여 특정한 소프트웨어 꾸러미, 소프트웨어 프레임워크, 하드웨어 플랫폼, 컴퓨터 시스템, 게임기, 운영 체제 등을 위한 응용 프로그램 등을 만들 수 있게 해주는 개발 도구의 집합
JRE(Java Runtime Environment)
- 자바를 실행하기 위한 환경
- JVM, Java 클래스 라이브러리, java명령 및 기타 인프라를 포함하여 컴파일 된 JAVA프로그램을 실행하는데 필요한 모든 것을 포함한 패키지
궁금한 점
가끔 블로그마다 JVM 구조 중 실행 엔진에 GC가 포함되어 있다고 나와있는 경우가 있는데, GC는 JVM 구조 중 하나로 따로 존재하는데 왜 실행 엔진 안에 GC가 포함되어 있다고 하는지?
답을 모르겠다 ㅜㅜ
바이트 코드를 컴파일 방식으로 처리하지 않고 인터프리터 방식으로 처리하는 이유?
- 자바: WORA(Write Once Run Anywhere) 의 특징, 플랫폼에 독립적
- JVM: 플랫폼(OS)에 종속적(자바로 작성된 프로그램을 특정 OS 에 맞게 변경을 해줘야 하기 때문)
→ 인터프리터 방식(class 파일을 해당 OS에 맞게 interpreter가 번역)을 사용하면 플랫폼에 구애받지 않을 수 있게 된다!
[ 참고 ]
- 자바는 크로스 플랫폼(멀티 플랫폼) 언어임
- 크로스 플랫폼(멀티 플랫폼): 다양한 플랫폼에서 사용 가능
- Java 컴파일러는 소스코드를 컴파일해서 "바이트 코드(Byte Code)"를 생성 → 그 바이트 코드를 자신의 운영체제에 맞게 설치된 JVM 위에서 실행시키기만 하면 됨
- 컴파일러
- 장점: 목적프로그램을 실행할때는 컴파일을 하지 않아 속도가 월등히 빠름
- 단점: 컴파일러는 한꺼번에 컴파일을 하기 때문에 컴파일 시간은 오래걸림
- 인터프리터
- 장점: 라인별로 컴파일을 하기 때문에 라인을 컴파일 하는 시간이 짧음, 플랫폼에 종속적이지 않음
- 단점: 프로그램을 실행하는 동안 컴파일 작업도 같이 하기 때문에 프로그램 자체의 속도는 느림
출처
https://jaeseongdev.github.io/development/2021/03/08/JAVA는_인터프리터_방식과_컴파일_방식이_혼합된_언어이다/
https://jooona.tistory.com/157
https://jooona.tistory.com/158
https://wonyong-jang.github.io/java/2020/11/08/Java-JVM.html
https://velog.io/@jaden_94/1주차-항해일지
https://github.com/Chohongjae/javaStudy/blob/main/live-study/week1.md
https://sowhat4.tistory.com/61
https://gblee1987.tistory.com/173
https://github.com/kksb0831/Practice_project/blob/master/Java_Study_01.md
https://aroundck.tistory.com/1949
https://blog.cordelia273.space/16
https://velog.io/@huttels/2020-04-19
'스터디 > whiteship - live-study' 카테고리의 다른 글
[백기선님 라이브 스터디] 3주차 - 연산자 (0) | 2022.04.11 |
---|---|
[백기선님 라이브 스터디] 2주차 - 자바 데이터 타입, 변수 그리고 배열 (0) | 2022.04.04 |
댓글