본문 바로가기
Java

Java JVM메모리 구조

by 내 멋대로 삶 2021. 12. 24.
JVM이란?

자바는 어느 OS에서도 동작이 되도록 설계되어 있는데 그 이유는 JVM(Java Virtual Machine)덕분이다.

JVM이 OS 와 Java사이에서 중계자 역활을 한다. 자바는 JVM이 OS에게서 메모리 사용권한을 할당 받고 JVM이 자바 프로그램을 호출하여 실행시킨다. 

- Java Virtual Machine
- JAVA와 OS 사이에서 중계자 역할
- JAVA가 OS에 구애받지 않고 재사용을 가능하게 해 줌
- 메모리 관리 기능(Garbage Collection)

※ JVM(java.exe)은 무엇을 하는가?

 메모리를 할당한다.

 bytecode를 interpreter 형태로 OS에 맞추어 번역, 실행한다.

 번역, 실행 시 최적화를 수행한다.

 

자바프로그램 실행과정

JVM의 구성을 살펴보면 크게 4가지(Class Loader, Execution Engine, Garbage Collector, Runtime Data Area)로나뉜다.

클래스 파일을 로딩한 뒤 검증하고 초기화하는 Class loader subSystem, 클래스 파일을 저장하는 Runtime DataArea(이곳은 다시 method area, heap, java stacks, pc registers, native method stacks의 5가지 영역으로 나누어진다), 클래스 파일(바이트코드)를 플랫폼에 맞는 기계어로 변환시켜 실행하는 Execution engine 이다. 참조되지 않는 객체들을 탐색후 삭제해 heap메모리를 재사용할 수 있게 해주는 Garbage Collector 이다.

 

  • Garbage Collector

1. 컴파일러는 무엇을 하는가?

① 사용자가 생성한 클래스 코드의 문법을 체크한다.

② 사용자가 생성한 클래스 코드에 컴파일러가 추가적으로 필요한 코드와 새로운 문법 코드를 삽입한다.

   - java.lang package의 import 기능 등 사용된 클래스들의 전체 패키지 경로를 식별

   - 상속이 없으면 object 기본 상속

   - 생성자가 없으면 기본생성자 삽입

   - 모든 메서드(생성자포함)에 첫번째 매개변수 this 추가

   - interface 라면 메소드에 public abstract 처리

   - Java 최신 버전의 문법 코드로 변경

③ 기본적인 최적화 작업을 수행

④ bytecode로 변환

 

2. Class Loader

자바에서 소스를 작성하면 Person.java 처럼 .java파일이 생성된다.

.java 소스를 자바컴파일러가 컴파일하면 Person.class 같은 .class파일(바이트코드)이 생성된다.

이렇게 생성된 클래스파일들을 엮어서 JVM이 운영체제로부터 할당받은 메모리영역인 Runtime Data Area로 적재하는 역할을 Class Loader가 한다. (자바 애플리케이션이 실행중일 때 이런 작업이 수행된다.)


3.Execution Engine

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

명령어를 하나 하나 실행하는 인터프리터(Interpreter)방식이 있고 JIT(Just-In-Time) 컴파일러를 이용하는 방식이 있다.

최초 JVM이 나왔을 당시에는 인터프리터 방식이었기때문에 속도가 느리다는 단점이 있었지만 JIT 컴파일러 방식을 통해 이 점을 보완하였습니다.

JIT는 바이트 코드를 어셈블러 같은 네이티브 코드로 바꿈으로써 실행이 빠르지만 역시 변환하는데 비용이 발생하였습니다. 이 같은 이유로 JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고, 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일러 방식으로 실행합니다.

 

4.Garbage Collector

Garbage Collector(GC)는 Heap 메모리 영역에 생성(적재)된 객체들 중에 참조되지 않는 객체들을 탐색 후 제거하는 역할을 한다.

GC가 역할을 하는 시간은 정확히 언제인지를 알 수 없다. (참조가 없어지자마자 해제되는 것을 보장하지 않음)

또 다른 특징은 GC가 수행되는 동안 GC를 수행하는 쓰레드가 아닌 다른 모든 쓰레드가 일시정지된다.

특히 Full GC가 일어나서 수 초간 모든 쓰레드가 정지한다면 장애로 이어지는 치명적인 문제가 생길 수 있는 것이다. (GC와 관련된 내용은 아래 Heap영역 메모리를 설명할 때 더 자세히 알아본다.)

 

5. Runtime Data Area

JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.

이 영역은 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 나눌 수 있다.

  • Method Area

- 멤버변수 이름,데이터타입,접근제어자 정보

- 메서드 이름,리턴타입,매개변수,접근제어자 정보

- class,interface 인지의 여부저장

- 상수풀, static 변수

  • Stack Area

- LIFO(Last In First Out)시스템

- 메서드 호출시 각 메서드를 위한 메모리 공간 생성

- 메서드에 사용되는 값을 저장 ->  호출된 매게변수,지역변수,리턴값 들을 임시로 저장

- 메서드 수행완료시  위에서 부터 프레임별로 삭제

  • Pc Register(PC 레지시터)

- Thread(쓰레드)가 생성될 때마다 생성되는 영역

- Program Counter 즉, 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다. (*CPU의 레지스터와 다름) 이것을 이용해서 쓰레드를 돌아가면서 수행할 수 있게 한다.

- Thread가 어떤 부분을 어떤 명령으로 실행할 지에 대한 기록

  • Native Method Stack

- 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역(보통 C/C++등의 코드를 수행하기 위한 스택이다.)

- 쓰레드가 생성되었을 때 기준으로 메소드 영역힙 영역은 모든 쓰레드가 공유하고,

- 스택 영역과 PC 레지스터, Native method stack은 각각의 쓰레드마다 생성되고 공유되지 않음

  • Heap Area & Garbage Collector

- Heap Area :

1. new 연산자로 생성된 객체와 배열을 저장하는 공간
2. 클래스 영역에 로드된 클래스만 생성가능

- Minor GC : New 영역에서 일어나는 GC

1. 최초에 객체가 생성되면 Eden영역에 생성된다.

2. Eden영역에 객체가 가득차게 되면 첫 번째 CG가 일어난다.

3. survivor1 영역에 Eden영역의 메모리를 그대로 복사된다. 그리고 survivor1 영역을 제외한 다른 영역의 객체를 제거한다.

4. Eden영역도 가득차고 survivor1영역도 가득차게된다면, Eden영역에 생성된 객체와 survivor1영역에 생성된 객체 중에 참조되고 있는 객체가 있는지 검사한다.

5. 참조 되고있지 않은 객체는 내버려두고 참조되고 있는 객체만 survivor2영역에 복사한다.

6. survivor2영역을 제외한 다른 영역의 객체들을 제거한다.

7. 위의 과정중에 일정 횟수이상 참조되고 있는 객체들을 survivor2에서 Old영역으로 이동시킨다.

- 위 과정을 계속 반복, survivor2영역까지 꽉차기 전에 계속해서 Old로 비움

 

- Major GC(Full GC) : Old 영역에서 일어나는 GC

1. Old 영역에 있는 모든 객체들을 검사하며 참조되고 있는지 확인한다.

2. 참조되지 않은 객체들을 모아 한 번에 제거한다.

- Minor GC보다 시간이 훨씬 많이 걸리고 실행중에 GC를 제외한 모든 쓰레드가 중지한다.

 

* Major GC(Full GC)가 일어나면,

Old영역에 있는 참조가 없는 객체들을 표시하고 그 해당 객체들을 모두 제거하게 된다.

그러면서 Heap 메모리 영역에 중간중간 구멍(제거되고 빈 메모리 공간)이 생기는데 이 부분을 없애기 위해 재구성을 하게 된다. (디스크 조각모음처럼 조각난 메모리를 정리함)

따라서 메모리를 옮기고 있는데 다른 쓰레드가 메모리를 사용해버리면 안되기 때문에 모든 쓰레드가 정지하게 되는 것이다.



 

 

참조 :https://jeong-pro.tistory.com/148 

https://cafe.naver.com/jjdev/227

 

'Java' 카테고리의 다른 글

자료구조 Array 구현  (0) 2022.03.23
equals와 hash code  (0) 2022.01.22
Java Jsoup,Selenium 크롤링 하기  (0) 2021.12.14
Array,List,ArrayList 의 차이  (0) 2021.12.01