본문 바로가기
[ 개발 지식 ]

JVM 구조

by 히앤님 2022. 9. 21.
반응형
SMALL

SMALL

JVM 구조

JVM : 자바가상머신. 자바 바이트코드를 실행시키는 주체. 운영체제 종류와 무관하게 가능
즉, 운영체제 위에서 동작하는 프로세스로 자바를 컴파일해서 얻은 바이트코드를 기계어로 바꿔서 실행시키는 역할.

1. 소스코드 -> 바이트코드

소스코드는 .java로 저장한다.이걸 자바 컴파일러(javac)가 바이트코드로 바꿔주는데 그건 .class로 저장한다.
왜? 일단 1차적으로는 코드 숨기기, byte코드로 바꾸면 문법검사같은건 안하게 되면서 실행 시간이 단축됨.
근데 이러면 소스코드 변경할때마다 또 컴파일러가 .class로 byte코드로 변경하니까 번거로움.

2. 바이트코드 -> Runtime Data Area

이렇게 변경된 byte코드(.class)파일들은  class Loader가 Runtime Data Area로 로딩시킨다.
Runtime Data Area는 5가지 영역으로 되어있는데,
1. 메소드영역 , 힙 영역 : 모든 스레드가 공유하는 영역
2. stack, PC Register, Native Method Stack : 스레드마다 하나씩 생성되는 공간
이렇게 나뉜다.

하나씩 보자.

1) method 영역

JVM이 시각될 때 생성되는 공간으로 byte코드(.class)가 여기에 저장된다.
그리고 모든 스레드가 공유하는 영역이니까 클래스의 정보, 변수 정보, static으로 선언한 공유변수가 저장되고 모든 스레드가 공유한다.

2) heap 영역

동적으로 생성된 객체가 저장되는 영역, 즉 new 연산으로 동적으로 생성된 인스턴스(클래스가 객체가 된 것)가 여기에 저장된다.
클래스의 객체, 배열 등 쉽게 소멸되지 않는 데이터가 있다.

heap 영역은 가비지 콜렉터(GC)의 영역이 된다. heap도 크게 3가지로 나뉘는데, young/old/permanent 이다.

2-1) GC(가비지 콜렉터)

가비지 콜렉터란 정리되지 않는 메모리, 유효하지 않는 메모리 주소로,
예를 들어 첫 초기화 이후에 값을 또 할당했을 때 값이 덮어씌워지는데, 그 전에 선언했던 값이라던지
선언은 해서 메모리는 가지고 있는데 사용이 되지 않은 값이라던지를 자바에서는 garbage라 부른다.
메모리가 부족할 때 가비지를 메모리에서 해제시키고 공간만들어주는 것이 GC의 역할.
크게 Mark와 Sweep 과정으로 나뉘는데,
Mark는 변수나 객체를 스캔하면서 어떤 객체 참조하는지 찾는 과정(=도달성(reacheable))이고(이때 스탑함),
Sweep는 Mark가 안된 객체를 힙에서 제거하는 과정이다.
GC가 Mark and Sweep를 거치며 가비지를 구분할 때 도달성(reachable)이라는 개념이 있는데,
객체에 유효한 레퍼런스가 있는지(=객체를 참조하는지)를 말한다.

2-2) Stop The World

GC가 실행되려면 JVM이 애플리케이션 실행을 잠시 멈춰야한다. 그걸 Stop The World라고 한다.
멈추는 시간을 줄이는 것을 GC 튜닝이라고 한다.

2-3)heap 영역의 구조

Young 영역에서 발생한 GC를 Minor GC, old/permanent 영역에서 발생한 GC를 Major GC(Full GC)라고 한다.

쉽게 말해 young은 새롭게 생성된 객체가 위치해서 대부분 생성되었다가 사라지는 곳.
old는 reachable 상태가 유지되서 살아남은 객체들 모음. GC가 적게 발생함.
perm은 메소드랑 비슷하다. 클래스와 메소드 정보가 들어있는 곳.


3) Stack 영역

스택은 지역변수나 메서드의 매개변수, 임시 사용된 변수, 메서드의 정보가 저장되는 영역.
지역변수나 매개변수는 메소드가 호출이 종료되면 그 안에 있는 변수는 사라진다.
즉, 금방선언되고 금방 사라지는 애들이 여기 있다가 없어진다.

즉, class a(변수명) = new 생성자명(생성자 안에 들어갈 데이터);


여기서 a는 스택에 저장된다. 생성자명(데이터)는 heap 영역에 저장된다.
왜? 원래 자바의 레퍼런스 타입(클래스,인터페이스,배열,상수)들은 구조가 복잡하고 용량이 크다.
이것들까지 스택에 보관해서 그때그때 뽑아쓰면 비효율적이므로 heap에다가 저장 후,
얘네들 주소를 참조하는 변수(a)를 스택에다가 저장해서 불러오는 것이다.


4) PC Register 영역

스레드가 어떤부분을 어떤 명령어로 수행할지 저장하는 공간.
스레드가 시작될 때 생성되며, 현재 수행되는 JVM 명령어 주소를 저장한다.

5) Native Method Stack 영역

자바를 제외하고 다른 언어,C언어나 C++언어가 실행되는 공간.
자바 프로그램이 컴파일 된 byte코드(.class)가 아니라 실제로 실행 가능한 기계어(0101)를 실행시키는 영역.

3. Runtime Data Area -> Execution Engine 영역 : 해석할 차례

로드된 클래스 파일의 byte코드를 실행하는 곳. 여기서 컴퓨터가 이해할 수 있는 기계어로 바꾼다.
방법은 두가지.

1. 인터프리터 : 명령어 한줄한줄 해석하면서 실행.

2. JIT(just-in-time) 컴파일러 : 한줄한줄말고 런타임에 전부 한번에 실행.
여기서 해석한 것을 다시 Runtime Data Area로 가져가서 배치하고 스레드가 동기화되거나 가비지 컬렉션에 들어간다.

4. JNI(Java Native Interface) 영역

추가로 JNI는 JDK의 일부분인데, 다른 언어로 쓰여져있는 애플리케이션이나 라이브러리가 자바 가상머신과 상호작용을 할 수 있게 도와준다.
 

▼ 더 자세하게 확인해보고 싶다면?

 

일반인에게 설명하는 [자바 프로그램의 실행 과정] - 2. 자바 프로그램 실행

그동안 소스코드를 작성하고 언어를 배우며 써왔지만 실제로 어떻게 동작하는지에 대해서는 등한시한 경향이 있었다. 일반인도 이해할 수 있게, 가장 많이 쓰이는 자바 프로그램이 어떻게 동작

heannim-world.tistory.com

반응형
LIST

댓글