Java는 어느 특정 OS에 종속되지 않고 어느 곳에서나 사용이 가능하다. 그 이유는 OS 위에서 Java를 실행시키기 위한 어느 무언가가 있기 때문인데 이것이 JVM이다.
Java 소스코드(*.java)는 JVM을 거쳐서 OS에 도달하게 된다. Java 소스코드는 기계어가 아니기에 컴파일의 과정이 필요하다.
그 과정을 Java Compiler가 담당하고 Java 소스코드를 Java bytecode(*.class)로 변환한다.
참고로 Java compiler는 javac.exe를 말한다.
해당 바이트코드는 기계어가 아니기에 OS에서 실행이 불가능하다. 그렇기에 한 번 더 해석하는 과정이 필요한데 이 과정을 JVM이 담당한다.
JVM은 자바 가상 머신으로 자바 바이트 코드를 OS에 특화된 코드로 변환(JIT 컴파일러, 인터프리터)하여 실행한다. 바이트 코드를 실행하는 표준이자 구현체다.
특징으로는 다음과 같다.
JIT 컴파일러는 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러로 인터프리터 방식의 단점을 보완하기 위해 도입하였다.
바이트코드를 읽어서 빠른 속도로 기계어를 생성할 수 있고 이 과정이 실시간으로 일어난다.
실행 시점에서 인터프리트 방식으로 기계어 코드를 생성하고 캐싱한다. 같은 함수가 여러 번 불릴 때에 매번 기계어 코드를 생성하는 것을 방지한다. 적절한 시점 이후에는 바이트 코드 전체를 컴파일해서 기계어로 변경한다.
또한 JIT 컴파일러가 컴파일하는 과정은 바이트 코드를 인터프리팅하는 것보다는 오래 걸리므로 한 번만 실행되는 코드일 때는 인터프리팅이 유리하다. 그렇기에 JVM은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넘을 때만 컴파일을 수행한다.
최적화를 미리 해주기 때문에 번역이 빠르게 진행되어 시간적으로도 이점을 갖게 되었고 가상 머신이 설치되어 있으면 빠르게 실행할 수 있다는 점 때문에 이식성이 뛰어나다고 할 수 있다.
인터프리터는 한 줄씩 번역하여 동시에 즉시 실행시키는 프로그램이다. 시분할 시스템에 유용하며 수정이 쉽다는 장점이 있다. 다만 실행 속도가 느리다는 단점이 있다. 목적 프로그램은 따로 생성하지 않는다.
메모리 관리 기법 중 하나. 동적으로 할당했던 메모리 영역 중 필요없게 된 영역을 해제하는 기능이다. 장점으로는 프로그래머가 동적으로 할당한 메모리 영역을 전체적으로 완벽하게 관리할 필요가 없어진다는 점이 있다.(Through-put, stop-the-world)
이 친구는 아예 따로 한 번 다뤄야 될 것 같다. 양이 좀 있다.
JVM이 프로그램을 수행하기 위해 OS로부터 별도로 할당받은 메모리 영역이다. PC Register, Navite Method Stack, JVM Stack은 각 쓰레드 별로 할당을 받고 Method Area, Heap은 쓰레드들이 공유한다.
현재 수행 중인 JVM 명령의 주소이다. 쓰레드가 시작될 때 생성되고 쓰레드마다 하나씩 존재한다. 현 쓰레드가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 한다.
Native Method를 호출하는 코드를 수행하기 위한 스택으로 자바가 아닌 언어에서 제공되는 메서드를 수행하기 위함이다. Java Native Interface를 통해서 바이트 코드로 전환하여 저장하게 되고 독자적으로 프로그램을 실행시키는 영역이다.
쓰레드가 시작될 때 생성이 되고 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역이다. 즉, 지역 변수, 파라미터, 기본 자료형, 리턴값 등 연산에 임시로 사용되는 정보들이 저장되는 영역이다. 또한 참조변수의 메모리 주소도 저장된다.
메서드가 수행될 때마다 하나의 스택 프레임이 생성되어 JVM Stack에 추가되고 종료되면 스택 프레임이 제거된다.
참고로 stack frame은 메서드가 호출될 때 그 메서드만의 스택 영역을 구분하기 위해 생성되는 공간을 말한다. JVM은
Class Area, Static Area라고도 한다. 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간이다. 즉, 메소드 정보, 클래스 정보, static 변수, final class, constant pool 등이 저장된다. 안에 Runtime Constant Pool이라는 영역이 따로 있는데 이 영역은 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.
인스턴스 변수의 데이터와 참조 자료형이 저장된다. Method Area에 로드된 클래스로만 객체 생성이 가능하다. JVM이 종료될 때까지, 가비지 컬렉터에서 지워질 때까지 메소드 호출이 끝나도 메모리에 유지된다.
해당 영역은 3 구역으로 나뉘어진다.
Native 키워드를 사용한 메서드 호출 구역으로 C, C++, 어셈블리 함수를 사용할 수 있는 방법을 제공한다.
JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미한다. 코드의 명령어 크기가 1바이트라 바이트 코드라고 한다. JIT 컴파일러 혹은 실시간 번역기에 의해 바이너리 코드로 변환된다.
Java를 사용하기 위한 기능을 갖춘 SDK이다. JRE + 개발 툴 구성이다. 소스 코드를 작성할 때 사용하는 자바 언어는 플랫폼에 독립적이다. 오라클은 자바 11부터 JDK만 제공하고 JRE를 따로 제공하지 않는다. 그 이유는 자바 9부터 모듈을 제공하기 때문에 그렇다.
Java 애플리케이션을 생성하고 실행하기 위한 구성요소로 JDK의 일부이다. JVM + Java 클래스 라이브러리로 구성된다. 개발 관련 도구는 포함하지 않고 JDK에서 제공한다. JVM, 핵심 라이브러리 및 자바 런타임 환경에서 사용하는 프로퍼티 세팅이나 리소스 파일을 가지고 있다.