JAVA Virtial Machine의 약자로 Java Byte Code를 OS에 맞게 해석해주는 역할을 하는 가상머신
JVM(java virtual machine)은 Java Byte Code를 OS에 맞게 해석 해주는 역할을 한다.
Java Compiler는 java 파일을 class 라는 java byte code로 변환 시켜 준다. byte code는 기계어가 아니기 때문에 바로 os에서 바로 실행되지 안ㄹ지만 여기서JVM이 bytecode를 이해할 수 있도록 해석해준다.
JVM의 해석을 거치기 때문에 c언어와 같은 네이티브 언어에 비해 속도가 느렸지만 JIT(Just In Time) 컴파일러를 구현해 이점을 극복했다.
Byte Code 는 JVM 위에서 os상관없이 실행된다. 이런점이 java의 가장 큰 장점이라고 할 수 있다. os에 종속적이지 않고 Java 파일 하나만 만들면 어느 디바이스든 JVM 위에서 실행 할 수 있다.
자바에서는 두가지 컴파일러 방식이 있다.
interpreter
jit compiler
javac fileName.java 수행하면 fileName.class이 만들어진다.
javac fileName.java
주요 javac 옵션은 아래와 같다.
옵션 | 설명 | 예제 |
---|---|---|
-classpath, -cp | 클래스패스, 즉 실행할 클래스의 위치를 지정한다. | javac -cp "/Users/home/A.java" |
-d | 어디에 클래스파일을 생성할지 지정한다. | javac -d "/User/home/path" |
-encoding | 소스 파일에 사용된 인코딩을 지정한다. | javac -encoding "uft-8" A.java |
-g | 모든 디버깅 정보를 출력 | javac -g ~~~ |
-verbose | 컴파일러가 진행하는 작업을 모두 출력한다. | javac -verbose ~~~ |
-sourcepath | 소스파일 위치 지정 | javac -sourcepath "/User/home/path" |
-source | 소스파일 자바 버전 지정 | javac -source 1.8 ~~~ |
-target | 타겟파일 자바 버전 지정 | javac -target 1.8 ~~~ |
java fileName.class
위 명령어로 실행할 때 JVM의 구성요소인 클래스로더가 fileName.class 파일을 메모리상의 JVM으로 가져온다.
내부적으로는 classLoader -> Byte Code Verifier (바이트코드 변조 확인) -> Execution Engine에서 실행된다.
Execution Engine에서 클래스파일(바이트코드로 구성)을 기계어로 변경해서 명령어 단위로 실행한다.
다만 명령어 단위 실행은 2가지 방식으로 동작한다.
Interpreter 방식: 명령어를 하나씩 수행 하는 방식
JIT(Just In Time compiler) 방식: 전체 바이트코드를 네이티브 코드로 변환하고 그 이후에는 네이티브 코드로 실행하는 방식
바이트코드(Bytecode, portable code, p-code)는 특정 하드웨어가 아닌 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법이다.
하드웨어가 아닌 소프트웨어에 의해 처리되기 때문에 보통 기계어 보다 더 추상적이다.
JVM이 사용자가 작성한 .java 소스 코드 파일을 운영체제에 실행 가능한 명령어 집합 파일로 컴파일 하는 과정 중에서 필요한 코드
JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미
자바 컴파일러에 의해 변환되는 코드의 명령어의 크기가 1byte라서 자바 바이트 코드라고 불림
자바 바이트 코드는 자바 가상 머신만 설치되어 있다면 어느 운영체제에서도 실행 가능
기존 클래스파일(바이트코드)를 실행하는 방법은 Interpreter 방식이 기본이다.
Interpreter 방식은 명령어를 하나씩 해석해서 처리하는 개념이기 때문에 명령어 하나하나 실행하는 속도는 빠를지 모르나 전체 코드 관점에서 보면 실행 속도가 느린 단점이 있다.
해당 문제를 해결하기 위해서 나온 방법이 JIT 컴파일러다.
JIT 컴파일 (just-in-time-compilation) 또는 동적 번역(dynamic translation)은 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일 기법이다.
즉, JIT 컴파일러는 같은 코드를 매번 해석하지 않고 실행할 때 컴파일을 하면서 해당 코드를 캐싱해버린다. 이후엔, 바뀐 부분만 컴파일 하고 나머지는 캐싱된 코드를 사용한다. 인터프리터의 속도를 개선 가능하다.
JVM은 크게 Class Loader
, Runtime Data Areas
, Excution Engine
, Garbage Collector
4가지로 구성되어 있다.
Class Loader
Runtime Data Areas
로딩, 링크, 초기화 순으로 진행
로딩
링크
초기화
클래스 로더는 계층 구조로 이뤄져 있으며 기본적으로 세가지 클래스 로더가 제공된다.
Delegation
Visibility
Uniquesness
JRE(Java Runtime Environment)
JDK(Java Development Kit)
애플리케이션을 JRE가 있으면 작동시킬 수 있다. 단, 운영할때 디버깅 및 분석 등을 하고자 하는 경우에는 JDK에 들어있는 도구가 필요하다. 따라서 서버 등의 운영 환경에 설치하는 경우에도 JRE보다는 JDK를 선택하는 것이 좋은 경우도 있다.
참조