-
JVM ARCHITECTURE (배경 , 특징 , 컴파일 과정 등)Java&Spring/Java 2023. 9. 15. 18:07
JVM (Java Virtual Machine)
2022 9월 28일 부터 지속적으로 글을 업데이트 중입니다.
Java의 특징 : "OS 에 종속 적이지 않고 실행 가능 하다"
배경
Java 로 작성한 코드는 JVM 에 의하여 동작을 하게 됩니다.
이로 인하여 이론상 OS 및 하드웨어의 관계없이 자바 언어로 어플리케이션 개발이 가능합니다.
JVM 은 많은 개발자의 C/C++ 로 개발시 복잡한 메모리의 할당 , 해제고민들로 부터 자유로워지게 만들었고 , OS 별로 고민을 해야할 많은 상황에서 자유롭게 만들었습니다.
주관적인 의견으로 개발의 난이도가 낮춰저 많은 인원이 하나의 서비스를 편하게 개발하는 단계가 시작이 되었다라고 생각합니다.
* GC 로 인하여 메모리가 할당된 객체,변수를 신경쓰지 않아도 된다하지만 , 메모리릭은 Java 어플리케이션에 나타날 수 있습니다.
관련 아티클 : Java memoryLick
특징
Java 코드든 os 로 부터 독립을 이루었지만 , JVM 은 OS 별로 다르기 때문에 , JVM 은 OS 에 종속적인 구조를 가집니다.
cf) 코틀린도JVM 에서 동작을 하는 언어입니다.
코틀린의 컴파일 과정과 자바의 컴파일 과정의 대략적인 그림을 가져왔습니다.
*하나의 프로젝트에서 두개의 언어로 작성한 코드들은 자바 컴파일이 먼저 일어나는 점을 알아두는게 좋습니다.
Java의 컴파일 및 실행 과정
1.
JavaC (Java compiler) 가 .java 파일을 이용하여 .class 라는 Java bytecode로 변환 시킨 파일을 생성합니다.
💡 여기서 Java compiler는 JDK를 설치하면 bin 에 존재하는 javac.exe를 말한다.
(즉, JDK에 Java compiler가 포함되어 있다는 소리임 ,JVM 안에 컴파일러가 있는거 아님)
javac 명령어를 통해 .java를 .class로 컴파일 할 수 있다.2.
JVM 의 클래스 로더에 의하여 클래스 파일을 실행 하게 됩니다.
JVM ARCHITECTURE
그림을 봅시다.
JVM 은 버젼별로 당연하게도 다양한 변경사항들이 있지만 , JVM 의 기본 구성요소 , 아키텍처는 대체로 일정합니다.
디스크의 있는 데이터를 메모리를 통해 cpu 에서 연산 작업을 하는 과정과 비교하면서 JVM 을 봅시다.
1. 디스크에 있는 데이터를 메모리에 최초로 올리는 과정
2. 메모리와 cpu 사이의 데이터를 서로 주고 받는 과정
1. 디스크에 있는 데이터를 메모리에 최초로 올리는 과정
Class Loader | 동적으로 바이트 코드를 JVM 메모리에 올리는 작업을 수행한다.
* 실제 메모리와 JVM 의 메모리 영역은 다릅니다.
클래스 로더의 역할
- 위에서 언급한 동적이라는 의미는 메모리에 필요한 클라스가 요청이 되면, Java Class Library 에서 동적으로 클라스 정보를 호출하게 됩니다. 한정된 메모리 자원을 생각하면 합당한 이유의 동작 방식으로 보입니다.
- 클래스가 필요로하는 메모리를 할당 , 클래스 로더에서 정적변수 초기화 작업이 일어납니다.
- 예시로 로컬 환경을 설명했지만 , 네트워크를 통한 바이트 정보에서 클래스 로딩도 가능합니다.
- 부트스트랩 클래스 로더(최상위 jvm 기본 내장) , 플랫폼 클래스 로더(과거 extension class loader), 시스템(어플리케이션) 클래스 로더로 구성이 됩니다.
2. 메모리와 cpu 사이의 데이터를 서로 주고 받는 과정
2.1 Memory Area of JVM (a.k.a RDA)
Runtime Data Area | 실행 중 필요한 데이터를 보관하는 가상 메모리 환경
크게 5개의 영역으로 나눌 수 있습니다. 메인 메모리의 구조와 비슷합니다.
- Head Area | 객체와 인스턴스 변수들을 저장, 배열의 할당 . new 키워드를 통한 인스턴스의 저장 장소.
- Method Area | Heap 영역에 저장이 되지 않은 코드속 각종 정보들의 저장소.
크래스 로더 참조, 타입 저장 , 메서드 데이터 저장 , 런타임 constant pool ,생성자 정보 등
- Stack Area | Stack 은 실행을 위한 메소드를 담는 저장소 .
메서드가 호출이 되면 스택에 메서드를 담고 , 종료되면 제거한다. FIFO
스레드 마다 stack 을 가지고 있다.
- PC register | 현재 thread 가 실행되는 명령어의 주소 저장소 .
JVM 이 명렁어를 한나씩 실행할때마다 , pc register 값을 변경 하여 다음 실행할 명령을 결정합니다.
- Native method Stack Area | Java 가 아닌 언어로 작성된 메서드의 저장소 .
💡 힙, 메서드 영역은 모든 스레드가 공유하고 있습니다.
멀티 스레드가 가능하게 하는 장점이자 그로 인하여 동시성 이슈가 발생할 수 있는 이유입니다.2.2 Excution Engine
Execution Engine | Runtime Data Area 와 상호 작용하여 바이트 코드를 실행하는 역할
다음과 같은 방식으로 바이트 코드를 실제 기계 내부에서 실행 할 수 있는 형태로 변경 합니다.
Interpreter | 명령어를 하나씩 읽어서 실행
- 바이트 코드 하나하나의 해석은 빠르지만 인터프린팅의 결과 실행은 컴파일 방식보다 느립니다.
Compiler - 추가적인 포스팅 예정
> 동적 컴파일 | JIT Compiler (Just In Time Compilation) - OpenJDK HotSpot VM
- 인터 프린팅 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일 하여 네이티브 코드로 변경 후 실행, 인터프린팅 보다 빠르고, 캐쉬를 통해서 개선이 가능합니다. .class -> .jar 로 바꿔 주는 역할이며 c1, c2 컴파일로 구성이 되어 있습니다.
> 정적 컴파일 | AOT Compiler (Ahead of Time Compilation) - GraalVM
매우 빠른 실행이 가능한 장점이 있는 컴파일 방식입니다.
💡Open JDK 17 에서 Graal JIT 컴파일러와 AoT가 빠지게 되었고 JVM compiler interface (JVMCI)만이 남았습니다.
open JDK docs : https://openjdk.org/jeps/4102.3 Garbage Collection
Garbage Collection | 메모리 관리 Runtime Data Area의 메모리 영역을 관리 하는 역할
- 주로 RDA 의 Heap Area를 관리합니다.
- 추가적인 포스팅 예정입니다.
💡 명령어를 사용해서 jdk 에서 사용하는 GC 의 종류를 알 수 있습니다.
> $ java -XX:+PrintCommandLineFlags -version
> ... -XX:+UseG1GC
> openjdk version "21" 2023-09-19 , JDK 21 기준 G1GC 가 기본으로 설정이 되어 있는 것을 확인 가능합니다.장리 및 결론)
- JVM 가상 머신이 이해하는 코드는 바이트 코드이며 , 컴파일러로 만든 파일을 JVM 이 호출하여 실행합니다 (.class file)
- CPU 가 이해 하는 것은 "바이너리 코드" 이며 "바이트 코드"가 아닙니다.
1.디스크에 있는 데이터를 메모리에 최초로 올리는 과정 : class loader
동적으로 클래스 로더를 통하여 바이트 코드를 가장 RDA 메모리에 올리며 전역 변수 영역을 초기화한다.
2.메모리와 cpu 사이의 데이터를 서로 주고 받는 과정 : RuntimeDataArea <-> Execution Engine
RDA 에 올린 메모리 정보를 jvm 내부 컴파일러를 통하여 cpu 가 실행 가능한 바이너리 코드로 변경을 하고 , GC 를 통하여 RDA 의 주로 힙 영역의 메모리를 관리 한다.
출처 :
0. Official Documents
https://www.oracle.com/java/technologies/javase/18all-relnotes.html
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html
블로그 ) 사진들의 출처 및 소스
0. [조금 더 깊은 Java] JRE의 Classloader 에 대해 알아보자
- 이해하기 가장 좋은 JVM 사진이 있습니다.
cf 코틀린 관련 이전 글입니다.
https://chosunghyun18.tistory.com/50
'Java&Spring > Java' 카테고리의 다른 글
[모던 자바 인 액션] part 1 - 1 (0) 2023.11.03 Genric 이 타입 일반화인 줄 만 알면, 주니어입니다. (1) 2023.09.04 자료구조 Stack , add vs push (0) 2023.09.04 Sort : Arrays.sort() vs Collections.sort() & 배열 다중 정렬 및 출력 (0) 2023.09.04 GC 기본 개념 , 종류 (0) 2023.09.04