티스토리 뷰

반응형

1. JVM이란?

JVM은 자바 가상 머신으로 Java Virtual Machine의 줄임말이다.
Java는 운영체제(OS)에 구애받지 않고 실행할 수 있는데 , JVM이 그 역할을 한다. 자바 프로그램은 컴퓨터가 이해할 수 있는 언어(기계어)인 바이너리코드가 아닌 바이트코드(가상 머신이 이해할 수 있는 코드)로 되어 있다. 여기서 JVM의 필요성을 알 수 있다. 기계어는 cpu의 제조사마다 달라서 하나의 언어가 아니다. 다 다른 컴퓨터 환경에서 실행하려면 각각의 제조사에 맞는 기계어를 알고 있어야 한다.

그렇지만 개발자가 모든 종류의 cpu의 기계어를 알고 있기에 매우 번거롭다.
그래서 JVM이 자바 프로그램을 다양한 cpu 환경에서 이식성 문제 없이 실행할 수 있도록 도와주는 역할을 하는 것이다.
이것이 운영체제에 구애받지 않는다는 말과 같다.

이에 대해 자세히 알아보기 위해 일단 Java의 컴파일, 실행 과정을 알아보자.


2. Java 컴파일과 실행 과정

빌드 시,


1) 개발자가 자바 소스 파일(.java)을 작성한다.
2) 자바 컴파일러(javac.exe)를 이용하여 자바 소스 파일(.java)을 컴파일한다. 이때 나오는 파일은 자바 바이트코드(.class)파일로 아직 컴퓨터가 읽을 수 없으며, JVM이 이해할 수 있는 중간 단계의 코드다. 바이트코드의 각 명령어는 1바이트 크기의 Opcode와 추가 피연산자로 이루어져 있다.


런타임 시,


1) 바이트 코드를 JVM의 클래스 로더(Class Loader)에게 전달한다.
2) 클래스 로더는 동적 로딩(Dynamic Loading)을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역(Runtime Data Areas), 즉 JVM의 메모리에 올린다.

클래스 로더의 동작
1) 로드 : 클래스 파일을 JVM의 메모리에 로드한다.
2) 검증 : 자바 언어 명세 및 JVM 명세에 명시된 대로 구성되어 있는 지 검사한다.
3) 준비 : 클래스가 필요로 하는 메모리를 할당한다. (필드, 메서드, 인터페이스 등)
4) 분석 : 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.
5) 초기화 : 클래스 변수들을 적절한 값으로 초기화한다. (static)


3) 실행 엔진(Execution Engine)은 JVM 메모리에 올라온 바이트코드들을 JVM 내부에서 기계가 실행할 수 있는 형태로 변경한다. 이 때 방식이 두가지가 있다.

- 인터프리터(Java Interpreter) : 바이트코드 명령어를 한 문장씩 읽어서 기계어로 바꿔준다. 그 후 변환된 코드를 실행한다. 각각 하나의 실행은 빠르지만 전체적인 실행 속도는 느리다는 단점이 있다.


- JIT 컴파일러(Just-In-Time Compiler) : 인터프리터의 단점을 보완하기 위해 도입된 방식으로 바이트코드 전체를 기계어(바이너리코드)로 바꾸는 방식이다. 그래서 빌드 시에 컴파일러는 속도가 더 느리다. 그 이후에는 해당 메서드를 더 이상 인터프리팅 하지 않고(캐싱) 바이너리코드로 직접 실행한다. 즉, 하나씩 인터프리팅하여 실행하는 것이 아니라 만들어 둔 실행파일만 읽으면 되므로 실행속도는 인터프리터보다 빠르다.


3. JVM 구성 요소

1) Class Loader : 위에서 설명했듯이, 런타임 시점에 클래스를 로딩하게 해주며 클래스의 인스턴스를 생성하면 클래스 로더를 통해 메모리에 로드한다.

2) Runtime Data Areas : JVM이 프로그램을 수행하기 위해서 OS로부터 별도로 할당 받은 메모리 공간이다.
크게 5가지 영역으로 나눈다.

- PC Reigster : 스레드가 시작될 때 생성되며 스레드마다 하나씩 존재한다. 스레드가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행중인 JVM 명령의 주소를 가진다.

- JVM Stack : 프로그램 실행 과정에서 임시로 할당되었다가 메서드를 빠져 나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역이다. 메서드와 메서드 정보(메서드의 매개변수, 지역변수, 임시변수, 메소드 호출 주소)를 스택에 쌓는다. 메서드를 호출할 때마다 각각의 스택 프레임(메서드를 위한 공간)이 생성된다. 메서드 수행이 끝나면 프레임별로 삭제를 한다.

- Native Method Stack : 기계어로 작성된 프로그램을 실행시키는 영역이다. 자바 외의 언어로 작성된 native 코드들을 위한 stack이다. Java Native Interface를 통해 호출되는 c/c++ 등의 코드를 수행하기 위한 stack이다. Native Method를 호출하게 되면 Native Method Stack에 새로운 스택 프레임을 생성하여 푸시한다. 이는 JVM 내부에 영향을 주지 않기 위함이다.

- Method Area : 클래스 정보를 처음 메모리 공간에 올릴 때 초기화 되는 대상을 저장하기 위한 메모리 공간이다. 모든 쓰레드가 공유하는 메모리 영역이다. 클래스, 인터페이스, 메서드, 필드, static 변수 등의 바이트 코드를 보관한다.

- Heap : 프로그램 상에서 런타임 시에 동적으로 할당하여 사용하는 영역이다. 클래스를 이용해 객체를 생성하면 힙에 저장된다. 공유되는 자원이다.


3) Execution Engine


4) GC(Garbage Collector)

 

 

4. JDK와 JRE ?

자바 소스를 컴파일하고 실행하기 위해서는 기본적으로 javac.exe와 java.exe 두 프로그램이 필요하다.
javac.exe는 자바 소스코드를 컴파일할때 사용하는 프로그램이고
→ $ javac 소스파일명.java

컴파일된 바이트 코드를 실행할때는 java.exe를 사용한다.
→ $ java 소스파일명

javac.exe는 JDK, java.exe는 JRE에 포함되어 있어서 JDK와 JRE 둘다 설치해야 하지만 요즘은 JDK에 JRE가 포함된 형태로 배포되고 있어서 JDK만 설치해도 된다.

- JDK : Java Development Kit 자바 프로그래밍 시 필요한 컴파일러 등 개발 도구들을 포함한다. 오라클 자바 11부터는 JRE를 포함하고 있으며 개발에 필요한 여러가지 툴을 제공한다.

- JRE : Java Runtime Environment로 바이트 코드로 컴파일된 자바 프로그램을 실행할 때 사용한다. JVM이 자바 프로그램을 동작시킬 때 필요한 라이브러리 파일들과 기타 파일들을 가지고 있다.

반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday