Backend/Java

JVM( Java Virtual Machine )을 알아보자!

Juwon2106 2022. 1. 12. 21:25
728x90

이번 포스팅에서는 

JVM 이란?

JVM 용어 정리

JVM의 흐름

JVM의 구조를 알아보겠습니다.

 

JVM 흐름도

JVM ( Java Virtual Machine : 자바 가상 머신 ) 이란?

우선 JVM의 탄생과정을 살펴보면 자바가 공개되기 전에는 모든 컴퓨터 프로그램들은 특정 운영체제에 맞게 작성되었기 때문에 새로운 운영체제가 생길 때마다 새로운 운영체제에 맞는 새로운 프로그램을 만들어야 했습니다.

 

JVM이 탄생한 이후로는 어떤 운영체제에서든지 실행할 수 있고 운영체제에 상관없이 독립적으로 관리할 수 있습니다.

 

또한 자동으로 가비지 컬렉터를 이용하여 메모리를 관리할 수 있는 강력한 장점이자 JVM의 특징입니다.

 

용어 정리

Java Source : Source code인 확장자. java로 사람이 작성한 또는 사람이 이해할 수 있는 코드입니다.

Java Compiler(javac) : 작성된 코드를 JVM이 이해할 수 있도록 변환해주는 역할입니다.

Java Byte Code : 자바 컴파일러(javac)가 byte code인. class 파일로 만들어 줍니다.

Class Loader : 클래스(. class)들을 JVM의 메모리 영역인 Runtime Data Area에 로딩합니다.

Execution Engine : 로딩된 클래스(.class)들을 Exucution을 통해 해석되고 메모리에 적재되어 명령을 수행합니다.

  

JVM의 실행 흐름

Java Compiler가 만든 Java Byte Code로 Class Loader에 의해서 메모리에 할당되고 Execution Engine에 의해 해석되며 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 실행됩니다.

 

이 과정에서 Execution Engine에 의해 Garbage Collection이 작동하며 스레드의 동기화가 이루어집니다.

 

Garbage Collection이란?

이하 GC는 메모리를 차지하고 있는 불필요한 객체를 정리하여 메모리 공간을 확보하는 작업입니다.

 

Java Runtime시 Heap에 저장되는 객체들이 계속해서 쌓이기 때문에 OutOfMemmory Exception이 발생할 수 있습니다.

 

그러므로 JVM는 주기적으로 사용하지 않는 객체들을 수집하고 정리하는 Garbage Collector를 실행합니다.

 

이후에 Garbage Collector는 메모리 할당, 사용 중인 메모리, 사용 중이지 않은 메모리를 확인하고 Garbage Collection 작업을 실행합니다.

 

Runtime Data Area의 5가지 메모리 영역

 

Method  Area

해석된 바이트코드가 저장되며 생성된 클래스, 변수, Static 변수, Final 변수 등의 데이터가 저장되고 모든 스레드가 공유합니다.

 

 

Heap 

동적( new 객체(); )으로 생성한 객체가 저장되는 영역입니다.

 

Heap 영역은 GC의 정리 대상이며 Method Area와 동일하게 모든 쓰레드가 공유합니다.

 

Heap에는 GC를 위한 5가지 영역이 세분화되어 나뉘지만 이번 포스팅에서는 다루지 않겠습니다. 

 

 

Stack

Stack은 Method Area와 Heap과는 다르게 쓰레드 별로 Stack을 가지고 있습니다.

 

이 영역에는 지역변수, 메서드의 매개변수, 메소드의 정보가 저장됩니다.

 

메소드 정보가 저장된다는 것은 Class Loader에 의해 로딩된 클래스는 동적( new )으로 생성( 객체화 )됩니다.

MemberDTO mem = new MemberDTO();

new 명령어는 Heap의 메모리 공간을 확인한 뒤에 Heap에 MemberDTO 객체를 저장하고 Stack에는 mem의 객체가 쌓이게 됩니다.

 

이때 Heap에 저장된 MemberDTO 객체는 Stack에 쌓인 mem 객체를 참조하는 역할을 합니다.

 

String 주원 = "juwon";
String juwon = "juwon";

if( 주원 == juwon ) System.out.prinln("같습니다");
if( 주원 != juwon ) System.out.prinln("다릅니다");

String은 참조값 비교를 하기 때문에 결과는 "같습니다"가 출력되고 같은 Heap의 객체를 참조하고 있기 때문입니다.

 

여기서 JVM은 왜 컴퓨터의 자체의 메모리 혹은 저장공간을 사용하지 않고 복잡한 Stack을 사용하는 이유가 뭘까요?

 

그 이유는 컴퓨터마다 사양이 다르고 어느 환경 혹은 운영체제에서 독립적으로 사용되어야 하기 때문에 복잡한 Stack을 구현하여 사용합니다.

 

PC Register ( Program Counter Register )

Stack과 마찬가지로 스레드 별로 PC Register를 가지고 있습니다.

 

스레드가 시작될 때 생성되며, 현재 수행 중인 JVM의 명령어의 주소와 해당 명령을 저장하는 공간입니다.

 

Native Method Stack

java 언어로 작성된 코드가 아닌 다른 언어로 작성된 코드를 저장하기 위한 영역입니다.

public static native Thread currentThread();

위 코드처럼 native가 붙어있는 코드가 저장됩니다.

 

Execution Engine

Runtime Data Area에서 로딩된 클래스들은 Execution Engine을 통하여 해석되고 기계어( 어셈블리어 )로 변환합니다.

 

변환하는 방식은 두 가지로 Interpreter 방식과 Just In Time( JIT ) 방식을 사용합니다.

 

Interpreter 방식

해석된 코드를 하나씩 하나씩 읽어 실행합니다.

속도가 느리다는 단점을 가지고 있습니다.

 

Just In Time 방식

Interpreter 방식의 단점을 보완하기 위하여 Interpreter 방식 도중 적절한 시점에 해석된 코드 전체를 컴파일하여 

네이티브 코드로 변경하고 이후 Interpreter하지 않고 변경한 네이티브 코드를 직접 실행하여 빠른 속도로 처리하는 방식입니다.

 

Native Method Interface, Native Method Library

Java언어가 아닌 다른 언어로 만들어진 코드의 고유기능을 사용할 수 있도록 하는 framework이며,

실행에 필요한 라이브러리를 가지고 있습니다.

 

이번 포스팅에선 JVM에 대한 전반적인 내용을 다뤄보았습니다.

728x90