1. JVM이란?
자바 공부를 시작하면 가장 먼저 왜 자바를 사용하는지를 배우게 된다.
그것은 결국 자바의 장점이 무엇인가를 배운다는 것인데, 그곳에서 항상 JVM을 만나게 된다.
JVM(Java Virtual Machine)을 우리말로 직역하면 자바 가상 기계 되겠다.
왜 이런 것이 필요할까?
여러 이유가 있겠지만 근본적으로는 우리가 사용하는 언어를 컴퓨터가 이해할 수 없기 때문이다.
컴퓨터는 0과1밖에 모르는 바보이지만 우리의 언어는 상당히 고급지고 복잡하기 때문에 서로 간의 적절한 합의가 필요한데, 그것이 바로 프로그래밍언어인 것이다.
그러면 JAVA를 작성해서 던져주면 바로 이해할 수 있느냐 하면 또 그것도 아니다.
운영체제가 자바 프로그램을 바로 실행할 수 없기 때문이다.
자바는 완전한 기계어가 아닌, 중간 단계의 바이트 코드이기 때문에 바로 실행 될 수 없다!
왜 그런 언어를 사용하나 싶을 수 있겠지만, 다 인간 편하라고 사용하는 것이다.
JAVA를 사용하면 사용자는 운영체제 를 신경 쓰지 않고 코드를 작성할 수 있다.
JVM이 운영체제와 인간 사이에서 통역사 역할을 해주기 때문이다.
여기서 자바의 장점을 찾을 수 있는데, 개발자는 운영체제와 상관없이 자바 프로그램을 개발할 수 있다.
사용자의 불편함을 알아서 해결해주는 고마운 기계라고 할 수 있겠다.
2. 작동방식
우리가 Java코드로 파일을 작성하게 되면 *. java 파일이 생성된다.
이 파일은 굉장히 사람 친화적인 언어이기 때문에 컴퓨터는 이해할 수가 없다. JVM도 마찬가지로 이해하지 못한다.
일단 통역사인 JVM을 이해시키기 위해 컴파일 과정을 거쳐 class파일로 컴파일해줘야 한다.
JVM은 이 바이트 코드 파일(*.class)을 운영체제에 맞게 기계어로 번역해 준다.
그렇게 비로소 우리가 작성한 코드가 실행될 수 있는 것이다.

3. JVM의 구조

크게 `클래스로더`, `실행엔진`, `런타임 데이터 영역`, `네이티브 메서드 인터페이스`, `네이티브 메소드 라이브러리` 5개로 나누어볼 수 있다.
3-1 클래스 로더(Class Loader)
컴파일한 자바 클래스 파일(*. class)을 JVM에 로드하는 역할이다.
클래스 로딩은 `로딩` > `링크` > `초기화` 3단계로 나뉘어 있다.
로딩(Loading) : 클래스 파일을 가져와서 JVM 메모리에 로드
링크(Linking) : 클래스 파일 검증
초기화(Initialization) : 클래스 변수 초기화
3-2 실행 엔진(Execution Engine)
`인터프리터(InterPreter)` ,`JIT`, `가비지 컬렉터(Garbage Collector)`로 구성되어 있다.
인터프리터(InterPreter) : JVM이 자바 바이트코드를 CPU가 이해할 수 있는 기계어로 변환하는 과정에서 사용되며, 바이트 코드를 한 줄씩 읽고 해석하며 실행한다.
JIT(Just-In-Time) 컴파일러 : 자주 실행되는 바이트코드를 기계어로 변환해서 캐싱 해두기 때문에 인터프리터의 단점을 보완할 수 있다.
가비지 컬렉터(Garbage Collector) : 가비지 컬렉터는 JVM이 Heap 메모리를 자동으로 관리하는 기능이다.
자동으로 객체를 관리해 주기 때문에 개발자는 생성만 열심히 하면 돼서 편리하다.
3-3 런타임 데이터 영역(Runtime Data Area)
Method Area : 클래스, 정적 변수를 저장한다.
Heap : 객체를 저장하며 가비지 컬렉션의 대상이 된다.
PC Register : 현재 실행 중인 명령어 주소를 저장한다.
JVM Stack : 메서드 호출 시 지역 변수를 저장한다.
Native Method Stack : 네이티브 코드 실행 시 사용한다.
1. 자바 클래스 파일이 클래스 로더를 통해 Method Area에 로드된다.
2. new 키워드로 객체를 생성하면 Heap 영역에 저장되고, 이 객체는 GC가 관리하게 된다.
3. 메서드가 호출되면 Stack 영역에 새로운 스택 프레임이 생성되며 메서드 내부의 지역변수, 매개변수, 연산 결과등이 Stack에 저장된다.
4. JVM은 PC Register를 사용해 현재 실행 중인 명령어의 위치를 추척하며 바이트 코드를 해석해 실행 엔진이 동작된다.
5. C 나 C++ 같은 네이티브 코드를 호출하면 Native Method Stack에서 실행된다.
6. 메서드 실행이 끝나면 Stack에서 해당 스택 프레임이 제거되며, 더 이상 사용되지 않는 객체는 GC가 제거한다.
3-4 네이티브 메서드 인터페이스(JNI)
자바 코드에서 C 나 C++ 같은 네이티브 코드를 호출할 때 사용한다.
❓자바 환경에서 왜 네이티브 코드를 사용할까?
OS에 종속적인 기능(하드웨어 관련)을 사용해야 할 때 사용해야 한다.
자바는 파일 시스템, 네트워크, 메모리 관리 등의 저수준 기능을 직접 제어하기 어렵고,
프린터, GPU, 센서 데이터 읽기 같은 하드웨어 제어 시에 네이티브 언어가 필요하다.
3-5 네이티브 메서드 인터페이스(JNI)
JNI를 통해 호출할 수 있는 네이티브 코드 라이브러리이다.
4. JVM의 장단점
4-1 JVM의 장점
✔️ 운영체제 독립성
자바 코드가 한 번 컴파일되면 어떤 OS에서도 실행가능하다.
Windows, Mac, Linux 등에서 동일한. class파일을 실행할 수 있다.
✔️ 자동 메모리 관리
개발자가 직접 메모리를 해제하지 않아도 돼서 편하며, 그만큼 낮은 진입장벽을 제공하는 효과가 있다.
✔️ 보안 강화
JVM 내부에서 실행되기 때문에 OS의 메모리에 직접 접근할 수 없다.
4-2 JVM의 단점
❗초기 실행 속도 지연
인터프리터 방식으로 한 줄씩 바이트코드를 해석하며 실행하기 때문에 느리다.
❗ 메모리 사용량 많음
JVM이 자체적으로 GC, JIT, 스레드 관리등을 수행하기 때문에 메모리 사용량이 크다.
❗ 네이티브 코드보다 성능 낮음
JVM을 거치기 때문에 OS에서 직접 실행되는 네이티브 코드보다 속도가 느릴 수 있다.
종합해 보면 JVM의 도움을 받기 때문에 편하지만, 편한 만큼 성능면에서 손해를 볼 수밖에 없는 것이다.
하지만 하드웨어의 스펙이 갈수록 좋아지고 있으며, 모든 상황에서 반드시 고성능이 필요한 것은 아니므로, 성능에서 타협을 충분히 볼 수 있을 경우 굉장히 좋은 것 같다.
편하다는 것은 그만큼 저렴해질 수 있다는 뜻이니까.
'JAVA' 카테고리의 다른 글
| [Java] GeoLite2 사용해 IP 위치 조회 기능 구현하기 (0) | 2025.02.18 |
|---|---|
| [Java] 자바로 엑셀 다루기 - Apache POI 라이브러리 사용법 (0) | 2025.02.16 |
| [Java] diamond operator is not supported 에러 (0) | 2025.02.14 |
| [Java] Math.random()의 취약성과 시큐어 코딩 (0) | 2024.11.19 |
| [Java] replaceAll() - 자바 특정 문자 변경 함수 (4) | 2024.07.23 |