▶JVM이 무엇인가?
- Java Virtual Machine
- 자바프로그램 실행환경을 만들어주는 SW
- JVM은 JRE(Java Runtime Enviorment)에 포함되어 있고, JRE는 JDK(Java Development Kit)에 포함되어 있음.
▶ JVM을 사용하는 이유
- JVM을 사용하면 하나의 바이트코드(.class)로 모든 플랫폼에서 동작 가능함
- 바이트코드는 사람이 쓰는 자바코드와 컴퓨터가 읽는 기계어의 중간단계임.
Java는 플랫폼에 종속적이지는 않지만, JVM은 플랫폼에 종속적이다.
▶ 자바 프로그램의 실행과정
- 자바로 개발된 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당한다.
- 자바컴파일러(javac)가 자바소스코드(.java)를 자바 바이트코드(.class)로 컴파일한다.
- Class Loader를 통해 JVM Runtime Data Area로 로딩.
- Runtime Data Area로 로딩된 .class 들은 Execution Engine을 통해 해석된다.
- 해석된 바이트코드(.class)는 Runtime Data Area의 각 영역에 배치되어 수행되며, 이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어진다.
▷ 바이트코드를 읽는 방식
- JVM은 바이트코드를 명령어 단위로 읽어서 해석한다.
- 해석하기 위해서 Interpreter방식과 JIT컴파일 방식을 혼합하여 사용하는데,
- Interpreter방식은 바이트 코드를 한줄씩 해석하고 실행하는 방식이고(초기 방식으로 속도가 느림),
- 느린 속도를 보완하기 위해 나온것이 JIT(Just In Time)컴파일 방식이다.
- JIT 컴파일러를 이용해 바이트코드를 실행하는 시점에 각 OS에 맞는 Native Code로 변환하여 실행속도를 개선하였다.
- 하지만, 바이트코드를 Native Code로 변환하는데에도 비용이 소모되므로, JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않는다.
- 인터프리터 방식을 사용하다가 일정기준이 넘어가면 JIT컴파일 방식으로 명령어를 실행한다.
▷ JIT 컴파일러란?
- JIT컴파일러는 같은 코드를 매번 해석하지 않고, 실행할 때 컴파일을 하면서 해당 코드를 캐싱해버린다.
- 이후에는 바뀐 부분만 컴파일하고, 나머지는 캐싱된 코드를 사용한다.
- JIT컴파일러는 OS에 맞게 바이트코드로 한번에 변환하여 실행하기 때문에 Java Interpreter방식보다 성능이 10~20배정도 더 좋다.
▶ JVM의 구조
▷ 클래스 로더(Class Loader)
자바는 동적으로 클래스를 읽어온다.
그러므로 프로그램이 실행중인 런타임에 모든 코드가 JVM과 연결된다.
이렇게 동적으로 클래스를 로팅해주는 역할을 하는것이 클래스로더이다.
클래스로더는 .class파일을 묶어서 JVM이 OS로부터 할당받은 메모리 영역인 Runtime Data Area로 적재한다.
▷ 실행엔진(Execution Engine)
클래스 로더에 의해 JVM으로 로드된 .Class 파일들은 Runtime Data Area의 Method Area 영역에 배치된다.
배치된 이후에 JVM은 Method Area의 .Class파일들을 실행엔진에 제공한다.
그 후 실행엔진은 .Class 파일을 명령어 단위로 읽어서 실행시킨다.
▷ 가비지 컬렉터(Garbage Collector)
JVM은 GC(Garbage Collector)를 이용하여 더는 사용하지 않는 메모리를 자동으로 회수한다.
즉, 개발자가 따로 메모리를 관리하지 않아도 되는데 이런 언어를 managed언어라고 부른다.
자바에서는 new키워드로 생성된 객체가 Heap영역으로 가게 되는데, Heap 메모리 영역에 생성된 객체들 중에 더이상 참조되지 않는 책체를을 탐색 후 제거하는 역할을 한다.
GC역할을 수행하는 스레드를 제외한 나머지 모든 스레드들은 일시정지 상태가 된다.
GC에 관해서 더 자세히 알고싶다면 저번에 쓴 글을 읽어보면 좋을 것 같다!
▶ Runtime Data Area
- JVM의 메모리 영역
- 자바 application을 실행할 때 사용되는 데이터들을 적재하는 영역
모든 스레드가 공유해서 사용하는 영역(GC의 대상)
- 힙영역(Heap Area)
- 메소드 영역(Method Area)
스레다마다 하나씩 생성되는 영역
- 스택영역(Stack Area)
- PC레지스터(PC Register)
- 네이티브 메소드 스택(Native Method Stack)
▷ 모든 스레드가 공유해서 사용하는 영역(GC의 대상)
메소드영역(Method Area)
클래스 멤버 면수의 이름, 데이터 타입, 접근 제어자정보 와 같은 각종 필드 정보들과 메소드 정보, 데이터Type정도, Constant pool, static변수, final class등이 생성되는 영역
힙영역(Heap Area)
- new키워드로 생성된 인스턴스와, 배열이 생성되는 영역
- 주기적으로 GC가 제거하는 영역
- Java8 부터는 Permanent Gen이 사라지고 Metaspace가 생겼다. PermGen은 Heap영역에 있었지만 MetaSpace는 OS가 관리하는 Native Memory 영역에 있음.
- Native Memory 영역은 OS가 자동으로 크기를 조절함. PermGen은 JVm에 의해 크기가 장제되어있었음.
- 즉, 각종 메타정보를 OS가 관리하는 영역으로 옮겨 PermGen의 사이즈 제한을 없앤것이라고 할 수 있음.
▷ 스레드마다 하나씩 생성되는 영역
스택영역(Stack Area)
지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값들이 생성되는 영역
PC레지스터 (PC Register)
- Thread가 생성될 때 마다 생성되는 영역
- 프로그램 카운터. 즉 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역
네이티브 메소드 스택 (Native Method Stack)
- 자바 이외의 언어로 작성된 네이티브 코드를 시랭할 때 사용되는 메모리 영역으로 일반적을 C스택을 사용한다.
- 보통 C/C++등의 코드를 수행하기 위한 스택을 말하며(JNI), 자바 컴파일러에 의해 변환된 자바 바이트코드를 읽고 해석하는 열할을 하는것이 자바 인터프리터이다.
'학과 공부 > Java' 카테고리의 다른 글
다형성이란? 오버로딩와 오버라이딩, @Override 어노테이션 (1) | 2024.04.18 |
---|---|
[Java] GC(Garbage Collector)에 대해서 알아보자 (0) | 2024.02.22 |
[Java] 자바 언어 시작하기(JDK 설치, 자바 환경변수 설정) (1) | 2024.02.04 |