일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 월간회고
- Blue-Green
- N+1
- InnoDB 버퍼 풀
- 도커
- DeleteAll
- Jenkins
- java
- 기능별 구조
- ci/cd
- 백기선 스터디
- 계층별 구조
- 카카오 2차 코딩테스트
- 주간회고
- jacoco
- 우테코
- db
- 멀티쓰레드 프로그래밍
- BalancedTree
- B+TREE
- useQuery
- mysql
- 클래스
- 어댑티브 해시 인덱스
- 프리코스
- useMutation
- 메서드명
- SQL 실행순서
- 회고
- 블로그 병행
- Today
- Total
Haneul's Blog
[Java] JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가. 본문
예전에 백기선님이 진행하셨던 스터디의 과제를 늦었지만 차근차근 따라가보려고 합니다.
자바를 어느정도 할 순 있지만 스터디의 진행을 따라가면 자바에 대해 조금 더 깊은 이해를 할 수 있을 것 같아 시작해보려 합니다.
먼저 1주차인 JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가 부터 시작하겠습니다.
목표 [백기선님 1주차 자바 스터디]
자바 소스 파일(.java)을 JVM으로 실행하는 과정 이야기
학습할 것
- JVM이란 무엇인가
- 컴파일 하는 방법
- 실행하는 방법
- 바이트코드란 무엇인가
- JIT 컴파일러란 무엇이며 어떻게 동작하는지
- JVM의 구성요소
- JDK와 JRE의 차이
JVM이란 무엇인가
JAVA Virtual Machine, 자바 머신의 약자를 따서 줄여 부르는 용어로, 자바를 실행하기 위한 가상 기계라고 할 수 있습니다.
Java는 OS에 종속적이지 않고 실행되기 위해서는 Java를 실행시킬 무엇인가가 필요한데 그것이 바로 JVM입니다.
하지만 JVM은 개발자가 작성한 코드인 .java 파일을 읽어들이지 못하기 때문에 바이트 코드 형태인 .class 파일로 변환해서 JVM에 넘겨주어야 합니다.
이러한 코드를 변환해주는 역할을 해주는 것이 Java Compiler이고, 자세한 내용은 밑에서 설명하겠습니다.
컴파일 하는 방법과 실행 방법
위에서 Java Compiler가 .java 파일을 .class 파일로 변환해준다고 말했는데, 여기서는 컴파일 하는 과정과 컴파일한 파일을 통해서 실행하는 방법을 설명드리겠습니다.
먼저 Java Compiler는 JDK를 설치하면 JDK의 bin 폴더에 javac.exe 라는 형태로 설치 되고 이를 통해서 javac라는 명령어를 사용하면 .class 파일을 생성할 수 있습니다.
예를 들어 test.java라는 파일이 있고 javac test.java 명령어를 통해서 test.class라는 바이트 코드로 이루어진 클래스 파일이 생성되게 됩니다.
이렇게 생성된 test.class 파일을 통해서 java test라는 명령어를 실행하게 되면 JVM의 Class Loader가 class 파일의 바이트 코드를 JVM 내로 적재해주고 JVM의 Execution engine을 통해 기계어로 해석되어 Runtime Data Area에 배치되게 되는 과정을 거쳐서 실행됩니다.
여기서 JVM의 Class Loader, Execution engine, Runtim Data Area라는 개념이 나오는데 이는 JVM의 구성요소에 대해서 정리할 때 설명드리겠습니다.
바이트 코드란 무엇인가
위에서 .class 파일은 바이트 코드로 이루어져 있다고 했는데, 바이트 코드란 무엇일까요?
개발을 하는 것은 사람이지만 프로그램을 실행하는 것은 컴퓨터입니다. 즉, 프로그램은 컴퓨터가 이해할 수 있는 형태로 작성되어 있어야 한다는 것입니다.
하지만 바이트 코드는 컴퓨터가 이해할 수 있는 언어는 아니고, 사람이 작성한 소스 코드를 JVM이 이해할 수 있게 중간 코드로 컴파일 된 언어를 의미합니다.
결국 바이트 코드는 사람이나 컴퓨터를 위한 언어가 아닌 JVM을 위한 언어라고 할 수 있습니다.
이러한 과정을 거치는 이유는 Java의 특징은 OS에 종속적이지 않게 하고 JVM을 통해서 실행될 수 있게 하기 위함입니다.
JIT 컴파일러란 무엇이며 어떻게 동작하는지
일정시간 동안 인터프리터가 코드를 해석하며 컴파일하기에도 충분할 정도로 자주 호출되는 메서드를 파악하여 해당 메소드만 컴파일 하는 방식입니다.
JIT 컴파일러에 의해 해석된 코드는 캐시에 보관하기 때문에 한 번 컴파일된 후에는 빠르게 수행할 수 있는 장점이 있습니다.
하지만 코드 전체를 컴파일 하기 때문에 인터프리팅을 하는 것보다 시간이 오래 걸려서 한 번만 실행해도 되는 코드는 인터프리팅하는 것이 유리합니다.
따라서 JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넘을 경우에 컴파일을 수행하는 것이 좋습니다.
사용되는 시점은 JVM이 바이트 코드를 실행할 때 JIT 컴파일을 통해 기계어로 변환합니다.
JVM의 구성요소
JVM은 크게 ClassLoader, Execution Engine, Runtim Data Area로 구성 되어 있습니다.
아래에 하나씩 자세하게 설명해보겠습니다.
ClassLoader
Class Loader는 JVM 내로 .class 파일을 로드하고, 링크를 통해서 배치하는 작업을 수행하는 모듈이며 런타임시에 동적으로 클래스를 로드하고 jar 파일 내 저장된 클래스들을 JVM 위에 탑재합니다.
정리하자면 변환된 ByteCode를 JVM이 운영체제로부터 할당 받은 메모리 영역인 Runtim Data Area에 적재하는 역할을 합니다.
Execution Engine
Class Loader를 통해서 JVM 내부로 넘어와 Runtime Data Area에 배치된 ByteCode들을 실행 해주는 역할을 합니다.
ByteCode는 위에서 말했다시피 기계가 실행할 수 있는 언어가 아니기에 Execution Engine은 이를 기계가 실행할 수 있는 형태로 변환시켜 줍니다.
Execution Engine에는 인터프리터, JIT 컴파일러, GC(가비지 콜렉터)가 있고 각각의 역할에 맞게 수행되게 됩니다.
인터프리터는 자바 바이트 코드를 명령어 단위로 읽어서 실행해주는 역할을 하며 한 줄씩 수행하기 때문에 느리다는 단점이 있습니다.
JIT 컴파일러는 위의 인터프리터만을 사용하면 같은 코드가 나와도 한 번 더 실행하게 되어 속도가 느리다는 점을 보완하기 위해 나온 것으로 자주 반복되는 코드를 컴파일하여 기계어로 변경하고 이후에는 인터프리팅하지 않고 기계어로 직접 실행하여 속도를 높여준 것입니다.
GC는 더이상 사용되지 않는 인스턴스를 찾아서 메모리에 삭제해줍니다. 이 때 삭제되는 대상은 Heap Area의 데이터들 뿐입니다.
Runtim Data Area
프로그램 수행을 위해서 OS에 할당받은 메모리 공간으로 Class Loader를 통해서 배치된 바이트 코드들과 컴파일된 기계어로 구성되어 있습니다.
Runtime Data Area는 PC Register, Stack Area, Heap Area, Native method stack, Method Area로 이루어져 있고 하나씩 밑에서 설명해보겠습니다.
PC Register
Thread가 실행될 때 생성되는 공간으로 Thread마다 하나씩 존재하며 Thread가 어떤 부분을 어떤 명령으로 실행해야 할지를 기록하는 부분입니다.
Stack Area
프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역으로 Stack 영역은 Thread 별로 각각 독립적으로 생성됩니다.
이 곳에는 각종 형태의 변수나 임시데이터, 스레드나 메소드의 정보를 저장하고, 호출된 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장합니다.
Heap Area
new 연산자로 생성된 객체와 배열을 저장하는 메모리 공간입니다.
또한 GC의 관리 대상이기도 합니다.
Native method stack
Java가 아닌 다른 언어로 작성된 코드를 위한 공간으로 자바 프로그램이 컴파일되어 생성되는 바이트 코드가 아닌 실제 수행할 수 있는 기계어로 작성된 프로그램을 실행 시키는 영역입니다.
Method Area
클래스와 인터페이스의 정보를 처음 메모리 공간에 올릴 때 초기화 되는 대상을 저장하기 위한 메모리 공간으로 Method Area는 모든 Thread에 공유되는 영역이며, JVM이 시작될 때 생성됩니다.
JDK와 JRE의 차이
이 둘의 관계는 사실 한 줄로 표현할 수 있습니다.
JDK = JRE + 개발에 필요한 도구
위의 공식을 보면 할 수 있듯이 JDK는 JRE에 개발에 필요한 도구를 더한 것입니다.
그렇다면 JRE가 무슨 역할을 하는지 유추해 볼 수 있습니다.
JRE
바로 자바의 실행환경을 만들어주는 것입니다. 이름도 JRE, Java Runtime Envireonment의 약자로 자바 실행환경을 의미합니다.
JAVA를 개발할 필요는 없는데, 실행은 시켜줘야 할 경우에는 JRE이 있어야 하며 JVM과 프로그램을 실행시킬 때 필요한 라이브러리 들이 포함되어 있습니다.
JDK
JDK는 자바 개발도구, Java Development Kit의 약자로 JAVA로 된 언어를 컴파일 하고 개발할 수 있도록 해주는 개발 환경의 세트를 의미합니다.
JDK는 JRE + 개발을 위한 도구인 javac, java, visualVM 등을 포함합니다.
'Java' 카테고리의 다른 글
[Java] 상속 (0) | 2022.10.17 |
---|---|
[Java] 클래스 (0) | 2022.10.16 |
[Java] 제어문 (0) | 2022.10.15 |
[Java] 연산자 (1) | 2022.10.13 |
[Java] 자바 데이터 타입, 변수 그리고 배열 (0) | 2022.10.12 |