JVM?

yeezze·2022년 7월 8일
0

Java

목록 보기
1/3

개발을 함에 있어서 여러가지 라이브러리나 놀라운 기술을 아는 것도 중요하지만 무엇보다 중요한 것은 개념과 기본을 제대로 알고있는게 중요한 것 같다. 그래서 Java의 개념에 대해서 공부해야겠다는 생각이 들었다.

개념

Java는 OS에 종속적이지 않은 언어이다. OS에 종속되지 않고 Java파일을 실행시키기 위해서는 OS 위에서 Java를 실행시킬 무언가가 필요하다.

JVM은 Java Virtual Machine의 줄임말이다.
Java를 실행시키기 위한 가상의 기계(컴퓨터)를 의미한다.

즉, OS에 종속받지 않고 CPU가 Java를 인식, 실행할 수 있게 하는 가상 컴퓨터이다.

java 소스코드(.java)는 CPU가 인식하지 못하기 때문에 기계어로 컴파일되는 과정이 필수적이다. 그런데 CPU가 실행하기 전에 JVM이라는 가상 머신을 거쳐서 도달하기 때문에 JVM이 알아들을 수 있는 언어로 먼저 번역해야한다. 때문에 Java bytecode(.class)로 먼저 변환된다.

Java compiler가 .java 파일을 .class 파일인 Java bytecode로 변환시킨다

변환된 Java bytecode는 기계어가 아니기 때문에 OS에서 바로 실행되지 않는다. 이때, JVM이 OS가 bytecode를 이해할 수 있도록 해석해준다. 따라서 Bytecode는 JVM 위에서 OS 상관없이 실행될 수 있다.
OS에 종속적이지 않고, Java 파일만 만들면 어느 디바이스든 JVM 위에서 실행할 수 있다.

컴파일하는 방법

Java Compiler는 JDK를 설치하면 javac.exe라는 실행 파일 형태로 설치된다. 정확히는 JDK의 bin 폴더에 존재한다. Java Compiler의 javac라는 명령어를 사용하면 .class파일을 생성할 수 있다.

javac 파일명.java

터미널에서 java 파일이 존재하는 위치로 이동 후 해당 명령어로 컴파일을 진행할 수 있다.

텍스트 편집기로 java 파일을 작성 후

터미널에서 명령어를 실행시키면 동일한 폴더에 class 파일이 생성됐다.

실행하는 방법

java 명령어로 JVM을 실행시킬 수 있다.

class 파일이 실행되면서 출력됐다.

바이트코드란?

  • 가상 컴퓨터(VM)에서 돌아가는 실행 프로그램을 위한 이진 표현법
  • 자바 컴파일러에 의해 변환된 코드의 명령어 크기가 1바이트라서 자바 바이트 코드라고 불리고 있다.

바이트코드는 다시 실시간 번역기 또는 JIT 컴파일러에 의해 바이너리 코드로 변환된다.

📌 바이너리 코드란?
바이너리 코드 또는 이진 코드라고 함
컴퓨터가 인식할 수 있는 0과 1로 구성된 이진코드

📌 기계어란?
0과 1로 이루어진 바이너리 코드이다.
기계어가 이진코드로 이루어졌을 뿐 모든 이진코드가 기계어인 것은 아니다.
기계어는 특정한 언어가 아니라 CPU가 이해하는 명령어 집합이며, CPU 제조사마다 기계어가 다를 수 있다.

즉, CPU가 이해하는 언어는 바이너리 코드, 가상머신이 이해하는 코드는 바이트 코드이다.

JIT 컴파일러란?

JIT 컴파일(just-in-time compliation) 또는 동적 번역이라고 한다.
JIT 컴파일러는 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러이다.

인터프리터 방식의 단점을 보완하기 위해 도입되었다.

인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 더이상 인터프리팅하지 않고 기계어로 직접 실행하는 방식

기계어(컴파일된 코드)는 캐시에 보관하기 때문에 한번 컴파일된 코드는 빠르게 수행하게 된다.
물론 JIT 컴파일러가 컴파일하는 과정은 바이트 코드를 인터프리팅하는 것보다 훨씬 오래 걸리므로 한번만 실행되는 코드라면 컴파일하지 않고 인터프리팅하는 것이 유리하다.
따라서 JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넘을 때에만 컴파일을 수행한다.

정리하면, 자바에서는 자바 컴파일러가 자바 코드를 바이트 코드로 변환 (.java -> .class)
실제 바이트 코드를 실행하는 시점에서 JVM이 바이트 코드를 JIT 컴파일러를 통해 기계어로 변환한다.

JVM 구성요소

  • 클래스 로더 (Class Loader)
  • 실행 엔진 (Execution Engine)
    • 인터프리터 (Interpreter)
    • JIT 컴파일러 (Just in time)
    • 가비지 콜렉터 (Garbage collector)
  • 런타임 데이터 영역 (Runtime Data Area)

클래스 로더

  • JVM 내로 클래스 파일(*.class)을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈
  • 런타임 시 동적으로 클래스를 로드하고 jar 파일 내 저장된 클래스들을 JVM 위에 탑재한다.
  • 즉, 클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링크하는 역할

실행 엔진

  • 클래스를 실행시키는 역할
  • 클래스 로더가 JVM 내의 런타임 데이터 영역에 바이트 코드를 배치시키고, 실행 엔진에 의해 실행된다.
  • 자바 바이트 코드(*.class)는 기계가 바로 수행할 수 있는 언어보다는 비교적 인간이 보기 편한 형태로 기술된 것이다. 그래서 실행 엔진은 이와 같은 바이트 코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경한다.

인터프리터

실행 엔진은 자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 하지만 한줄씩 수행하기 때문에 느리다.

JIT 컴파일러

인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 기계어로 컴파일하여 변경하고, 이후에는 더이상 인터프리팅하지 않고 기계어로 직접 실행하는 방식

가비지 콜렉터

더이상 사용되지 않는 인스턴스를 찾아 메모리에서 삭제함

Runtime Data Area

프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간 (static, stack, heap)

PC Register

  • 스레드마다 하나씩 존재
  • 스레드가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행 중인 JVM 명령의 주소를 갖는다.

JVM stack

  • 프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역
  • 메소드 호출 시마다 각각의 스택 프레임이 생성된다. 수행이 끝나면 프레임 별로 삭제.
  • 메소드 안에서 사용되는 값들 저장(지역변수, 리턴값 및 임시값들)

Method Area

  • static 영역 (필드에 선언된 전역변수, static 변수)
  • 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상 저장

Heap 영역

객체(인스턴스)와 배열 저장

출처

profile
백엔드 개발자 😊

0개의 댓글