JVM(Java Virtual Machine)
자바를 실행하기 위한 가상 기계
- 자바로 작성된 애플리케이션은 모두 이 가상 컴퓨터(JVM)에서만 실행되기에 자바 애플리케이션이 실행되기 위해서는 반드시 JVM이 필요
- 일반 애플리케이션의 코드는 운영체제만 거치고 하드웨어로 전달되는데 비해 JAVA 애플리케이션은 JVM을 한번 더 거치고, 하드웨어에 맞게 완전히 컴파일된 상태가 아니고 실행 시에 해석되기 때문에 속도가 느리다는 단점을 가지고 있다
- 그러나 요즘엔 바이트코드(컴파일 된 자바 코드)를 하드웨어의 기계어로 바로 변환해주는 JIT 컴파일러와 향상된 최적화 기술이 적용되어서 속도의 격차를 많이 줄였다
위 그림과 같이 일반 애플리케이션은 OS와 바로 맞붙어 있기에 OS종속적이다 그래서 다른 OS에서 실행시키기 위해서는 애플리케이션을 그 OS에 맞게 변경해야한다. 반면에 JAVA 애플리케이션은 JVM하고만 상호작용을 하기 때문에 OS와 하드웨어에 독립적이라 다른 OS에서도 프로그램의 변경없이 실행이 가능하다. 단 JVM은 OS에 종속적이기에 해당 OS에서 실행가능한 JVM이 필요
JDK(Java Development Kit)
자바 개발 도구
- JDK 설치시 JVM과 자바클래스 라이브러리(Java API)외에 자바를 개발하는데 필요한 프로그램들이 설치된다
- JRE를 포함하고 있다
JDK bin 디렉토리 주요 실행파일
- javac.exe : 자바 컴파일러, 자바소스코드를 바이트코드로 컴파일
- java.exe : 자바 인터프리터, 컴파일러가 생성한 바이트코드를 해석하고 실행
- javap.exe : 역어셈블러, 컴파일된 클래스파일을 원래의 소스로 변환
- javadoc.exe : 자동문서생성기, 주석을 이용해 Java API문서와 같은 형식의 문서 자동 생성
- jar.exe : 압축프로그램, 클래스파일과 프로그램 실행 관련 파일을 하나의 jar파일로 압축 or 압축해제
Java의 소스코드는 CPU가 인식하지 못해 기계어로 컴파일 해줘야 한다
class Hi
public static void main(String[] args){
System.out.println("Hello, world.");
}
}
위 코드를 실행하려면
1. 먼저 자바컴파일러(javac.exe)를 사용해 소스파일(Hijava)로부터 클래스파일(Hiclass)을 생성(바이트코드)
2. 바이트코드를 JVM 내의 자바 인터프리터(java.exe)로 실행한다
Hi.java -> Hi.class -> "Hello, world." 출력
바이트코드란?
- 자바 바이트코드는 JVM이 이해할 수 있는 언어로 변환된 소스코드
- 자바 컴파일러에 의해 변환된 코드의 명령어 크기가 1바이트라서 자바 바이트 코드라고 불리고 있다.
- 바이트코드는 JVM의 인터프리터, JIT 컴파일러를 통해 바이너리코드(컴퓨터가 인식할 수 있는 0과 1로 구성된 이진코드)로 번역된다
Java 동작과정 정리
- 소스코드 작성
- 컴파일러(javac)를 이용해 바이트코드로 변환
- JVM의 인터프리터, JIT 컴파일러를 이용해 바이너리코드로 변환
JVM의 구조
- 클래스로더(Class Loader)
- 실행엔진(Execute Engine)
- 런타임 데이터 영역(Runtime Data Area)
클래스로더
- JVM내로 클래스파일(바이트코드)을 로드하고 링크를 통해 배치하는 작업을 수행하는 모듈
- 자바는 동적 로드, 즉 컴파일 타임이 아니라 런타임(바이트 코드를 실행할 때)에 클래스 로드하고 링크하는 특징이 있다. 이 동적 로드를 담당하는 부분이 JVM의 클래스 로더
실행엔진
- 클래스를 실행시키는 역할
- 인터프리터
- 실행 엔진은 자바 바이트 코드를 명령어 단위로 읽어서 실행한다.
- 하지만 한 줄씩 수행하기 때문에 느리다는 단점이 있다
- JIT 컴파일러
- 인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 해당 더 이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식
- Garbage Collector
- 더이상 사용되지 않는 인스턴스를 찾아 메모리에서 삭제
런타임 데이터 영역
프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간
PC Registers
Thread가 시작될 때 생성되며 생성될 때마다 생성되는 공간으로, 스레드마다 하나씩 존재한다.
Thread가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행 중인 JVM 명령의 주소를 갖는다.
프로세스란?
단순히 실행 중인 프로그램(program)
즉, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 의미
스레드란?
스레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미
모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행한다.
또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 한다.
Java Stack
- 프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역이다.
Native Method Stack
- 자바 프로그램이 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역.
Method Area
- 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간
- Runtime Constant Pool
- 스태틱 영역에 존재하는 별도의 관리영역.
- 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.
Heap Area
- 객체를 저장하는 가상메모리 공간. new 연산자로 생성되는 객체와 배열을 저장한다.
- Class Area(Static Area)에 올라온 클래스들만 객체로 생성
글을 정리하며 느낀점
- 자바의 동작과정을 구체적으로 알게되었고 JVM에서 정확히 인터프리터와 JIT컴파일러가 어떤식으로 동작하는지, 정확히 어떻게 JIT 컴파일러의 사용으로 자바성능이 개선되는지 알게되었다
- JVM 구조에 따른 구체적인 기능과 JVM 메모리 구조를 더욱 잘 알게 됨
- 클래스로더의 구조와 JVM 메모리구조를 더욱 구체적으로 정리하고 싶었지만 내용이
더욱 방대해지므로 따로 정리한 글을 적어야겠다 >> 클래스로더 정리글
와! 정말 알고싶은 정보였어요!