JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가
JVM이란 무엇인가
**자바 가상 머신(Java Virtual Machine)**은 자바가 운영체제에 독립적으로 작동할 수 있도록 하는 소프트웨어이다. 즉, JVM은 컴파일된 자바 소스코드인 바이트코드를 실행하기 위해 각각의 운영체제에 맞는 기계어로 변환시킨다. 따라서 자바는 운영체제에 독립적이지만, JVM은 운영체제에 따라 바이트코드를 알맞은 기계어로 바꾸어야 하므로 운영체제에 종속적이다.
자바가 배포될 때, 자바 개발 도구인 JDK(Java Development Kit)가 자바 실행 환경인 JRE(Java Runtime Environment)를 포함하고, JRE는 JVM을 포함한다. 이 때 JDK에는 자바소스 컴파일러인 javac.exe가 포함되어있고, JRE는 자바프로그램 실행기인 java.exe를 포함한다. 즉, JDK를 통해 개발된 프로그램이 컴파일러(javac.exe) 를 통해 바이트코드로 변환되며, 이 변환된 바이트코드는 자바실행환경에 의하여 자바 가상 머신 위에서 구동된다(java.exe)
또한 JVM은 자동으로 메모리를 관리하는데, 실행하지 않는 메모리를 Garbage Collector를 통해 메모리를 자동해체 한다. 따라서 개발자는 메모리 관리를 염두하지 않고 프로그래밍에 집중할 수 있다. C나 C++에서는, 배열 혹은 포인터 등에서 메모리 동적할당 후, delete나 dealloc과 같은 메모리 해체 처리를 해주어야 한다. 그렇지 않으면 Memory leak이 발생한다.
컴파일 하는 방법
일반적으로 컴파일은 컴퓨터가 이해할 수 있는 기계어로 번역하는 것이다. 자바에서의 컴파일은 JVM이 이해할 수 있는 바이트코드로 변환하는 것이다.
자바 개발도구인 JDK에 있는 javac.exe가 자바소스를 컴파일하여 바이트코드로 변환한다.
cmd 환경에서 자바 파일을 컴파일하는 방법은 어렵지 않다. 자바 파일이 위치한 디렉토리에서,
javac fileName.java
를 입력하면 된다.
실행하는 방법
각각의 운영체제에 맞게 컴파일된 바이트코드는 JVM위에서 JRE에 있는 java.exe 를 통해 실행된다.
컴파일 된 자바 파일을 실행하는 방법은
java fileName
이다.
바이트코드란 무엇인가
JVM이 이해할 수 있는 중간코드이다. 일반적으로 컴파일은 소스코드를 컴퓨터가 이해할 수 있는 기계어로의 변환을 뜻하지만, 자바에서는 소스코드를 일종의 가상 컴퓨터인 JVM이 이해할 수 있는 바이크코드 형식으로 변환한 것을 뜻한다. 따라서 JVM은 기계어가 아니라 중간코드라고 말하는 것이 타당하다.
JIT 컴파일러란 무엇이며 어떻게 동작하는지
JIT(Just In Time) 컴파일러는 실행 시점에 기계어 코드를 생성한다. 기계어 변환이 코드가 실행될 때 실시간으로 이루어지기 때문에, Just In Time이다. 같은 코드가 반복되면 매번 기계어 코드를 생성하는 것이 아니라 이전에 만든 기계어를 재사용하는데, 이는 캐시에 변환된 기계어가 저장되기 때문이다. 실행시간이 오래걸리는 최적화 과정은 바이트코드 컴파일러가 대신하기 때문에 속도가 빠르다. 또한 운영체제에 맞게 바이트 실행코드로 한 번에 변환하여 실행하므로 이전의 자바 인터프리터 보다 성능이 좋다.
JVM 구성요소
Class Loader(클래스 로더)
클래스 로더는 말 그대로 클래스(.class 파일)을 로드한다. JVM 내로 클래스(.class 파일)로 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다. Runtime 시에 동적으로 클래스를 로드한다.
클래스 로더의 종류에는 Bootstrap, Extension, Application 세 종류가 있다.
Bootstrap Class Loader
- 클래스 로더 세 종류 중 최상위 클래스 로더인데, jre/lib/rt.jar에 담긴 JDK 클래스 파일을 로딩한다.
- Native C로 구현되어 있어서, **String.class.getClassLoader( )**는 null을 반환한다.
Extension Class Loader
- jre/lib/ext 폴더나 java.ext.dirs 환경변수로 지정된 폴더에 있는 클래스 파일을 로딩한다.
- 자바로 구현되었으며, sun.misc.Launcher 클래스 안에 static 클래스로 구현되어있고, URLClassLoader를 상속한다
Applicatoin Class Loader
- -classpath (또는 -cp)나 JAR 파일 안에 있는 Manifest파일의 Class-Path 속성값으로 지정된 폴더에 있는 클래스를 로딩
- 자바로 구현되었으며, sun.misc.Launcher 클래스 안에 static 클래스로 구현되어있고, URLClassLoader를 상속한다
- 개발자가 작성한 대부분의 클래스는 애플리케이션 클래스 로더가 로딩한다
Execution Engine(실행 엔진)
클래스를 실행시킨다. 클래스 로더에 의해 JVM에 배치된 바이트 코드들을 실행 엔진이 실행한다. 자바 바이트코드는 기계어가 아닌 중간코드이므로, 실행 엔진은 바이트코드를 JVM에서 이해할 수 있는 기계어로 변환한다.
Runtime Data Area
프로그램을 수행하기 위해 운영체제로 부터 메모리를 할당받은 곳이다.
-
PC Register
쓰레드가 시작될 때 마다 생성되며, 각 쓰레드 별로 하나씩 존재한다. 쓰레드가 어떤 부분을 어떤 명령으로 실행할지에 대해 기록하는 부분으로, 현재 수행중인 JVM의 명령의 주소를 갖는다.
-
JVM Stack
프로그램 실행 시 임시로 할당되었다가 메소드를 빠져나가면 사라지는 데이터를 임시적으로 저장하는 영역이다. 다양한 형태의 변수나 임시 데이터, 쓰레드, 메소드의 정보를 저장한다. 메소드를 호출할 때 마다 그 메서드만을 위한 공간인 스택 프레임이 생성되고, 수행이 끝나면 프레임별로 삭제를 한다.
-
Native Method Stack
바이트코드가 아닌 실제 기계어로 작성된 프로그램을 실행하는 영역이다. 즉 자바가 아닌 다른 언어로 작성된 코드들이다. 이 영역에 저장된 코드들은 Java Native Interface를 통해 바이트코드로 전환되어 저장된다.
-
Method Area
클래스 정보를 처음 메모리 공간에 올릴 때, 초기화되는 대상을 저장하는 공간이다. 올라가는 정보의 종류는, 멤버변수의 이름과 데이터 타입, 접근 제어자에 대한 정보인 Field Information과, 메소드의 이름, 리턴타입, 매개변수, 접근제어자에 대한 정보인 Method Information, 마지막으로 class인지 interface인지에 대한 정보와, Type의 속성, 이름, super class의 전체 이름에 대한 정보인 Type Infomation이 올라간다. 컴파일된 바이트코드 대부분은 메소드 바이트코드이기 때문에 거의 모든 바이트코드는 이 영역에 올라간다. Runtime Constant Pool은 상수 자료형을 저장하고 참조하여 중복을 막는다.
-
Heap
인스턴스화된 모든 클래스 인스턴스와 배열, 객체를 저장하는데 모든 JVM 쓰레드에 공유되는 공유자원이다. 힙에 할당된 메모리들은 무조건 가비지 컬렉터를 통해 이루어진다.
JDK와 JRE의 차이
JDK와 정확한 명칭은 Java Development Kit 즉, 자바 개발 도구이고, JRE의 정확한 명칭은 Java Runtime Environment, 즉 자바 실행 환경이다. 자바 프로그램이 구동되는 자바 가상 기계에서, JDK는 JVM용 소프트웨어를 개발하기 위한 도구이다. JRE는 일종의 JVM 속 OS라고 봐야한다. 자바 개발 도구인 JDK를 이영해 개발된 프로그램은 JRE에 의해 가상의 컴퓨터인 JVM 위에서 구동되는 것이다.
자바가 배포될 때, 자바 개발 도구인 JDK(Java Development Kit)가 자바 실행 환경인 JRE(Java Runtime Environment)를 포함하고, JRE는 JVM을 포함한다. 이 때 JDK에는 자바소스 컴파일러인 javac.exe가 포함되어있고, JRE는 자바프로그램 실행기인 java.exe를 포함한다. 즉, JDK를 통해 개발된 프로그램이 컴파일러(javac.exe) 를 통해 바이트코드로 변환되며, 이 변환된 바이트코드는 자바실행환경에 의하여 자바 가상 머신 위에서 구동된다(java.exe)
-
출처
https://asfirstalways.tistory.com/158 [블로그]
https://homoefficio.github.io/2018/10/13/Java-클래스로더-훑어보기/ [블로그]
스프링 입문을 위한 자바 객체 지향의 원리와 이해 [책]
Do it! 자바 프로그래밍 입문 [책]