본문 바로가기
Programming/Java

[JAVA] JVM(Java Virtual Machine) 자바 가상 머신 / Runtime Data Area

by prinha 2020. 8. 15.
728x90
반응형

 

"WORA (Write Once, Run Anywhere)" - Sun Microsystems

자바 코드를 컴파일해서 배포하면 어떤 플랫폼(운영체제+CPU 아키텍쳐)이든 다시 컴파일할 필요없이 실행할 수 있다.

단, 그 플랫폼에 맞는 JVM이 설치되어 있을 때!

 

c/c++도 크로스 컴파일을 해서 배포하면 되는데 굳이 JVM이 필요할까?
- 애초에 자바는 네트워크에 연결된 모든 디바이스에서 작동하는 것이 목적이었다.
- 디바이스마다 운영체제나 하드웨어가 다르기때문에 플랫폼에 의존하지 않도록 자바 언어를 설계했다.


 

JDK(Java Development Kit)

- JRE + 개발 툴(java c)
- 자바 11부터는 JDK 단위로 배포됨

JRE(Java Runtime Environment)
- JVM + 핵심 라이브러리
- 개발 관련X / 실행 관련O
- java는 보통 JRE 단위로 배포됨

JVM(Java Virtual Machine)
- Java Bytecode를 실행하기 위해 사용하는 메모리 공간
- CPU나 운영체제의 종류와 무관하게 실행이 가능(플랫폼에 종속적)
- .class파일을 OS에 맞는 기계어로 변환(인터프리터 & JIT 컴파일러)
- JVM의 구성은 크게 4가지 (Class Loader, Execution Engine, Garbage Collector, Runtime Data Area)

 

.java가 프로세스 되기까지의 과정 
.java -> (javac) -> .class -> (jvm) -> process 

Byte코드와 Binary코드의 차이 
Byte코드는 JVM같은 가상 머신이 이해할 수 있는 코드(=.class) 
Binary코드는 CPU가 이해할 수 있는 코드

 


 JVM의 구조 

 

· Class Loader System

생성된 클래스파일들을 엮어서 JVM이 운영체제로부터 할당받은 메모리영역(Runtime Data Area)로 적재하는 역할
로딩(.class를 읽어옴) -> 링크(코드 내부의 레퍼런스를 연결함) -> 초기화(클래스에 있는 static 값들을 초기화)

 

· Execution Engine

클래스 로더에 의해 메모리에 적재된 클래스(바이트 코드)들을 기계어로 변환해 명령어 단위로 실행하는 역할


1) 인터프리터

바이트 코드를 하나 하나 네이티브 코드로 변환


2) JIT(Just In Time) 컴파일러

바이트 코드에서 반복되는 코드 부분은 JIT 컴파일러가 미리 네이티브 코드로 변환
반복되는 코드가 읽힐 순서가 되었을 때, 인터프리터로 읽지않고 바로 네이티브 코드를 사용한다.
인터프리터가 읽을 때의 속도 효율성을 JIT 컴파일러가 보완하는 형태이다.


3) Garbage Collector
Heap 메모리 영역에 생성(적재)된 객체들 중에서 더이상 참조되지않는 객체를 탐색 후 제거 -> 메모리 정리
GC가 수행되는 동안 GC를 수행하는 스레드가 아닌 다른 모든 스레드들은 일시정지된다.
특히 Full GC가 일어나서 수 초간 모든 쓰레드가 정지한다면 장애로 이어지는 치명적인 문제가 생길 수 있다.
경우에 따라 성능 효율을 위해 커스터마이징을 해야한다.
Heap영역이 GC의 주요 대상이나 Stack영역과 Method영역도 GC의 대상이 된다.

 

· Runtime Data area 구조(메모리)

[힙, 메소드]는 전체 공유 자원으로 모든 스레드가 공유한다.
[스택, PC, 네이티브 메소드 스택]은 각 스레드마다 하나씩 존재하고 공유되지않는다.

 
1) Method area(메소드 영역) : 클래스 수준의 정보가 저장되는 영역 

 - 필드 정보(클래스의 멤버 변수명, 데이터 타입, 접근 제어자)
 - 메소드 정보(메소드명, 리턴  타입, 파라미터, 접근 제어자)
 - Type정보(Interface인지 class인지)
 - Constant Poll(상수 풀 : 문자 상수, 타입, 필드, 객체 참조)
 - static 변수, final 변수 등


2) Heap area(힙 영역) : new 키워드로 생성된 객체(인스턴스)와 배열이 저장되는 영역  

메소드 영역에 로드된 클래스만 생성이 가능하고, GC가 참조되지않는 메모리를 확인하고 제거하는 영역이다.

ex) Person p = new Person();이라는 소스를 작성했다면 Person p는 스택 영역에 생성되고,
new로 생성된 Person 클래스의 인스턴스는 힙 영역에 생성된다. 

 
3) Stack area(스택 영역) : 참조 주소 저장 영역

지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되고 저장되는 영역(참조 주소 저장) 
자바 스택은 스레드 별로 1개만 존재하고, 스택 프레임은 메소드가 호출될 때마다 생성된다. 

메소드 실행이 끝나면 스택 프레임은 pop되어 스택에서 제거된다.
stack안에 stack frame이 생성되는데 맨위(메인 메소드)-> 그 밑(메인메소드에서 호출한 메소드)....반복(메소드 호출 트레이스)

stack frame 
스택 프레임은 메소드가 호출될 때마다 새로 생겨 스택에 push된다.
스택 프레임은 Local variables array, Operand stack, Frame Data를 갖는다.
Frame Data는 Constant Pool, 이전 스택 프레임에 대한 정보, 현재 메소드가 속한 클래스/객체에 대한 참조 등의 정보를 갖는다.

ex) int a=10; 이라는 소스를 작성했을 때, 정수 값이 할당될 수 있는 메모리공간을 a라고 잡아두고
그 메모리 영역에 10이라는 값이 들어간다.
즉, 스택 메모리에 이름을 a라고 붙여주고 값이 10인 메모리 공간을 생성한다.
Person p = new Person();이라는 소스를 작성했다면 Person p는 스택 영역에 생성되고 
new로 생성된 Person 클래스의 인스턴스는 힙 영역에 생성된다.
그리고 스택 영역에 생성된 p의 값으로 힙 영역의 주소값을 가지고 있다.
즉, 스택 영역에 생성된 p가 힙 영역에 생성된 객체를 가리키고(참조)있는 것이다.

 
4) PC Regisster(PC 레지스터) : Program Counter 

스레드가 생성될 때마다 생성되는 영역으로, 현재 스레드가 실행되는 부분의 주소와 명령을 저장한다.
이것을 이용하여 스레드를 돌아가면서 수행할 수 있게 한다.

 
5) Native Method Stack(네이티브 메소드 스택)

자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역 

보통 C/C++ 등의 코드를 수행하기 위한 스택(JNI)
public static native Thread currentThread()로 선언되어 있다.

 


출처 및 참고

dailyheumsi.tistory.com/196

jeong-pro.tistory.com/148

www.youtube.com/watch?v=UzaGOXKVhwU

 

 

 

728x90
반응형